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.
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest allocation roundup size boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44 /* Only roundup for Windows clients. */
45 enum remote_arch_types ra_type = get_remote_arch();
46 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47 val = SMB_ROUNDUP(val,rval);
52 /********************************************************************
53 Given a stat buffer return the allocated size on disk, taking into
55 ********************************************************************/
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
64 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
67 if (!ret && fsp && fsp->initial_allocation_size)
68 ret = fsp->initial_allocation_size;
70 return smb_roundup(conn, ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 struct ea_list *next, *prev;
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
122 if (fsp && fsp->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
137 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138 dump_data(10, val, sizeret);
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
146 pea->value.data = (unsigned char *)val;
147 pea->value.length = (size_t)sizeret;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
157 /* Get a list of all xattrs. Max namesize is 64k. */
158 size_t ea_namelist_size = 1024;
163 struct ea_list *ea_list_head = NULL;
167 if (!lp_ea_support(SNUM(conn))) {
171 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
172 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
173 if (fsp && fsp->fd != -1) {
174 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
179 if (sizeret == -1 && errno == ERANGE) {
180 ea_namelist_size *= 2;
189 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
192 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
193 struct ea_list *listp, *tmp;
195 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
198 listp = TALLOC_P(mem_ctx, struct ea_list);
202 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
208 push_ascii_fstring(dos_ea_name, listp->ea.name);
209 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
210 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
211 *pea_total_len, dos_ea_name,
212 (unsigned int)listp->ea.value.length ));
214 DLIST_ADD_END(ea_list_head, listp, tmp);
216 /* Add on 4 for total length. */
217 if (*pea_total_len) {
222 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
226 /****************************************************************************
227 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229 ****************************************************************************/
231 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
232 connection_struct *conn, struct ea_list *ea_list)
234 unsigned int ret_data_size = 4;
237 SMB_ASSERT(total_data_size >= 4);
240 if (!lp_ea_support(SNUM(conn))) {
244 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
247 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
248 dos_namelen = strlen(dos_ea_name);
249 if (dos_namelen > 255 || dos_namelen == 0) {
252 if (ea_list->ea.value.length > 65535) {
255 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
259 /* We know we have room. */
260 SCVAL(p,0,ea_list->ea.flags);
261 SCVAL(p,1,dos_namelen);
262 SSVAL(p,2,ea_list->ea.value.length);
263 fstrcpy(p+4, dos_ea_name);
264 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
266 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
267 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
270 ret_data_size = PTR_DIFF(p, pdata);
271 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
272 SIVAL(pdata,0,ret_data_size);
273 return ret_data_size;
276 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
278 size_t total_ea_len = 0;
279 TALLOC_CTX *mem_ctx = NULL;
281 if (!lp_ea_support(SNUM(conn))) {
284 mem_ctx = talloc_init("estimate_ea_size");
285 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
286 talloc_destroy(mem_ctx);
290 /****************************************************************************
291 Ensure the EA name is case insensitive by matching any existing EA name.
292 ****************************************************************************/
294 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
297 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
298 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
300 for (; ea_list; ea_list = ea_list->next) {
301 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
302 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
303 &unix_ea_name[5], ea_list->ea.name));
304 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
308 talloc_destroy(mem_ctx);
311 /****************************************************************************
312 Set or delete an extended attribute.
313 ****************************************************************************/
315 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
316 char *pdata, int total_data)
318 unsigned int namelen;
321 fstring unix_ea_name;
323 if (!lp_ea_support(SNUM(conn))) {
324 return NT_STATUS_EAS_NOT_SUPPORTED;
327 if (total_data < 8) {
328 return NT_STATUS_INVALID_PARAMETER;
331 if (IVAL(pdata,0) > total_data) {
332 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
333 return NT_STATUS_INVALID_PARAMETER;
337 namelen = CVAL(pdata,1);
338 ealen = SVAL(pdata,2);
340 if (total_data < 8 + namelen + 1 + ealen) {
341 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
342 (unsigned int)total_data, namelen, ealen));
343 return NT_STATUS_INVALID_PARAMETER;
346 if (pdata[namelen] != '\0') {
347 DEBUG(10,("set_ea: ea name not null terminated\n"));
348 return NT_STATUS_INVALID_PARAMETER;
351 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
352 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
353 pdata += (namelen + 1);
355 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
357 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
359 DEBUG(10,("set_ea: data :\n"));
360 dump_data(10, pdata, ealen);
363 if (samba_private_attr_name(unix_ea_name)) {
364 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
365 return NT_STATUS_ACCESS_DENIED;
369 /* Remove the attribute. */
370 if (fsp && (fsp->fd != -1)) {
371 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
372 unix_ea_name, fsp->fsp_name));
373 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
375 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
376 unix_ea_name, fname));
377 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
380 /* Removing a non existent attribute always succeeds. */
381 if (ret == -1 && errno == ENOATTR) {
382 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
387 if (fsp && (fsp->fd != -1)) {
388 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
389 unix_ea_name, fsp->fsp_name));
390 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
392 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
393 unix_ea_name, fname));
394 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
400 if (errno == ENOTSUP) {
401 return NT_STATUS_EAS_NOT_SUPPORTED;
404 return map_nt_error_from_unix(errno);
410 /****************************************************************************
411 Read a list of EA's from an incoming data buffer. Create an ea_list with them.
412 ****************************************************************************/
414 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
416 struct ea_list *ea_list_head = NULL;
419 while (offset + 2 < data_size) {
421 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
422 unsigned int namelen = CVAL(pdata,offset);
424 offset++; /* Go past the namelen byte. */
425 if (offset + namelen >= data_size) {
428 eal->ea.name = TALLOC_ARRAY(ctx, char, namelen + 1);
432 memcpy(eal->ea.name, pdata + offset, namelen);
433 eal->ea.name[namelen] = '\0';
435 offset += (namelen + 1); /* Go past the name + terminating zero. */
436 DLIST_ADD_END(ea_list_head, eal, tmp);
442 /****************************************************************************
443 Send the required number of replies back.
444 We assume all fields other than the data fields are
445 set correctly for the type of call.
446 HACK ! Always assumes smb_setup field is zero.
447 ****************************************************************************/
449 static int send_trans2_replies(char *outbuf,
456 /* As we are using a protocol > LANMAN1 then the max_send
457 variable must have been set in the sessetupX call.
458 This takes precedence over the max_xmit field in the
459 global struct. These different max_xmit variables should
460 be merged as this is now too confusing */
463 int data_to_send = datasize;
464 int params_to_send = paramsize;
468 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
469 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
470 int data_alignment_offset = 0;
472 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
474 set_message(outbuf,10,0,True);
476 /* If there genuinely are no parameters or data to send just send the empty packet */
478 if(params_to_send == 0 && data_to_send == 0) {
479 if (!send_smb(smbd_server_fd(),outbuf))
480 exit_server("send_trans2_replies: send_smb failed.");
484 /* When sending params and data ensure that both are nicely aligned */
485 /* Only do this alignment when there is also data to send - else
486 can cause NT redirector problems. */
488 if (((params_to_send % 4) != 0) && (data_to_send != 0))
489 data_alignment_offset = 4 - (params_to_send % 4);
491 /* Space is bufsize minus Netbios over TCP header minus SMB header */
492 /* The alignment_offset is to align the param bytes on an even byte
493 boundary. NT 4.0 Beta needs this to work correctly. */
495 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
497 /* useable_space can never be more than max_send minus the alignment offset. */
499 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
501 while (params_to_send || data_to_send) {
502 /* Calculate whether we will totally or partially fill this packet */
504 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
506 /* We can never send more than useable_space */
508 * Note that 'useable_space' does not include the alignment offsets,
509 * but we must include the alignment offsets in the calculation of
510 * the length of the data we send over the wire, as the alignment offsets
511 * are sent here. Fix from Marc_Jacobsen@hp.com.
514 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
516 set_message(outbuf, 10, total_sent_thistime, True);
518 /* Set total params and data to be sent */
519 SSVAL(outbuf,smb_tprcnt,paramsize);
520 SSVAL(outbuf,smb_tdrcnt,datasize);
522 /* Calculate how many parameters and data we can fit into
523 * this packet. Parameters get precedence
526 params_sent_thistime = MIN(params_to_send,useable_space);
527 data_sent_thistime = useable_space - params_sent_thistime;
528 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
530 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
532 /* smb_proff is the offset from the start of the SMB header to the
533 parameter bytes, however the first 4 bytes of outbuf are
534 the Netbios over TCP header. Thus use smb_base() to subtract
535 them from the calculation */
537 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
539 if(params_sent_thistime == 0)
540 SSVAL(outbuf,smb_prdisp,0);
542 /* Absolute displacement of param bytes sent in this packet */
543 SSVAL(outbuf,smb_prdisp,pp - params);
545 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
546 if(data_sent_thistime == 0) {
547 SSVAL(outbuf,smb_droff,0);
548 SSVAL(outbuf,smb_drdisp, 0);
550 /* The offset of the data bytes is the offset of the
551 parameter bytes plus the number of parameters being sent this time */
552 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
553 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
554 SSVAL(outbuf,smb_drdisp, pd - pdata);
557 /* Copy the param bytes into the packet */
559 if(params_sent_thistime)
560 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
562 /* Copy in the data bytes */
563 if(data_sent_thistime)
564 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
565 data_alignment_offset,pd,data_sent_thistime);
567 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
568 params_sent_thistime, data_sent_thistime, useable_space));
569 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
570 params_to_send, data_to_send, paramsize, datasize));
572 /* Send the packet */
573 if (!send_smb(smbd_server_fd(),outbuf))
574 exit_server("send_trans2_replies: send_smb failed.");
576 pp += params_sent_thistime;
577 pd += data_sent_thistime;
579 params_to_send -= params_sent_thistime;
580 data_to_send -= data_sent_thistime;
583 if(params_to_send < 0 || data_to_send < 0) {
584 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
585 params_to_send, data_to_send));
593 /****************************************************************************
594 Reply to a TRANSACT2_OPEN.
595 ****************************************************************************/
597 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
598 char **pparams, int total_params, char **ppdata, int total_data,
599 unsigned int max_data_bytes)
601 char *params = *pparams;
606 BOOL return_additional_info;
615 int fmode=0,mtime=0,rmode;
617 SMB_STRUCT_STAT sbuf;
619 BOOL bad_path = False;
624 * Ensure we have enough parameters to perform the operation.
627 if (total_params < 29)
628 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
630 open_mode = SVAL(params, 2);
631 open_attr = SVAL(params,6);
632 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
634 return_additional_info = BITSETW(params,0);
635 open_sattr = SVAL(params, 4);
636 open_time = make_unix_date3(params+8);
638 open_ofun = SVAL(params,12);
639 open_size = IVAL(params,14);
643 return(ERROR_DOS(ERRSRV,ERRaccess));
645 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
646 if (!NT_STATUS_IS_OK(status)) {
647 return ERROR_NT(status);
650 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
651 fname,open_mode, open_attr, open_ofun, open_size));
653 /* XXXX we need to handle passed times, sattr and flags */
655 unix_convert(fname,conn,0,&bad_path,&sbuf);
657 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
660 if (!check_name(fname,conn)) {
661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
664 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
665 oplock_request, &rmode,&smb_action);
668 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
669 /* We have re-scheduled this call. */
670 clear_cached_errors();
673 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
676 size = get_file_size(sbuf);
677 fmode = dos_mode(conn,fname,&sbuf);
678 mtime = sbuf.st_mtime;
681 close_file(fsp,False);
682 return(ERROR_DOS(ERRDOS,ERRnoaccess));
685 /* Realloc the size of parameters and data we will return */
686 params = SMB_REALLOC(*pparams, 28);
688 return(ERROR_DOS(ERRDOS,ERRnomem));
691 memset((char *)params,'\0',28);
692 SSVAL(params,0,fsp->fnum);
693 SSVAL(params,2,fmode);
694 put_dos_date2(params,4, mtime);
695 SIVAL(params,8, (uint32)size);
696 SSVAL(params,12,rmode);
698 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
699 smb_action |= EXTENDED_OPLOCK_GRANTED;
701 SSVAL(params,18,smb_action);
704 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
706 SIVAL(params,20,inode);
708 /* Send the required number of replies */
709 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
714 /*********************************************************
715 Routine to check if a given string matches exactly.
716 as a special case a mask of "." does NOT match. That
717 is required for correct wildcard semantics
718 Case can be significant or not.
719 **********************************************************/
721 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
723 if (mask[0] == '.' && mask[1] == 0)
726 return strcmp(str,mask)==0;
727 if (StrCaseCmp(str,mask) != 0) {
730 if (ms_has_wild(str)) {
736 /****************************************************************************
737 Return the filetype for UNIX extensions.
738 ****************************************************************************/
740 static uint32 unix_filetype(mode_t mode)
743 return UNIX_TYPE_FILE;
744 else if(S_ISDIR(mode))
745 return UNIX_TYPE_DIR;
747 else if(S_ISLNK(mode))
748 return UNIX_TYPE_SYMLINK;
751 else if(S_ISCHR(mode))
752 return UNIX_TYPE_CHARDEV;
755 else if(S_ISBLK(mode))
756 return UNIX_TYPE_BLKDEV;
759 else if(S_ISFIFO(mode))
760 return UNIX_TYPE_FIFO;
763 else if(S_ISSOCK(mode))
764 return UNIX_TYPE_SOCKET;
767 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
768 return UNIX_TYPE_UNKNOWN;
771 /****************************************************************************
772 Map wire perms onto standard UNIX permissions. Obey share restrictions.
773 ****************************************************************************/
775 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
779 if (perms == SMB_MODE_NO_CHANGE)
782 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
783 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
784 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
785 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
786 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
787 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
788 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
789 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
790 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
792 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
795 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
798 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
801 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
802 ret &= lp_dir_mask(SNUM(conn));
803 /* Add in force bits */
804 ret |= lp_force_dir_mode(SNUM(conn));
806 /* Apply mode mask */
807 ret &= lp_create_mask(SNUM(conn));
808 /* Add in force bits */
809 ret |= lp_force_create_mode(SNUM(conn));
815 /****************************************************************************
816 Get a level dependent lanman2 dir entry.
817 ****************************************************************************/
819 static BOOL get_lanman2_dir_entry(connection_struct *conn,
820 void *inbuf, void *outbuf,
821 char *path_mask,int dirtype,int info_level,
822 int requires_resume_key,
823 BOOL dont_descend,char **ppdata,
824 char *base_data, int space_remaining,
825 BOOL *out_of_space, BOOL *got_exact_match,
830 SMB_STRUCT_STAT sbuf;
834 char *p, *q, *pdata = *ppdata;
838 SMB_OFF_T file_size = 0;
839 SMB_BIG_UINT allocation_size = 0;
841 time_t mdate=0, adate=0, cdate=0;
843 char *last_entry_ptr;
845 int nt_extmode; /* Used for NT connections instead of mode */
846 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
849 *out_of_space = False;
850 *got_exact_match = False;
855 p = strrchr_m(path_mask,'/');
862 pstrcpy(mask, path_mask);
867 /* Needed if we run out of space */
868 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
869 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
872 * Due to bugs in NT client redirectors we are not using
873 * resume keys any more - set them to zero.
874 * Check out the related comments in findfirst/findnext.
880 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
881 (long)conn->dirptr,curr_dirpos));
886 pstrcpy(fname,dname);
888 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
889 got_match = mask_match(fname, mask, conn->case_sensitive);
891 if(!got_match && !mangle_is_8_3(fname, False)) {
894 * It turns out that NT matches wildcards against
895 * both long *and* short names. This may explain some
896 * of the wildcard wierdness from old DOS clients
897 * that some people have been seeing.... JRA.
901 pstrcpy( newname, fname);
902 mangle_map( newname, True, False, SNUM(conn));
903 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
904 got_match = mask_match(newname, mask, conn->case_sensitive);
908 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
909 if (dont_descend && !isdots)
912 pstrcpy(pathreal,conn->dirpath);
914 pstrcat(pathreal,"/");
915 pstrcat(pathreal,dname);
917 if (INFO_LEVEL_IS_UNIX(info_level)) {
918 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
919 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
920 pathreal,strerror(errno)));
923 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
925 /* Needed to show the msdfs symlinks as
928 if(lp_host_msdfs() &&
929 lp_msdfs_root(SNUM(conn)) &&
930 is_msdfs_link(conn, pathreal, NULL, NULL,
933 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
934 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
938 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
939 pathreal,strerror(errno)));
944 mode = dos_mode(conn,pathreal,&sbuf);
946 if (!dir_check_ftype(conn,mode,dirtype)) {
947 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
951 file_size = get_file_size(sbuf);
952 allocation_size = get_allocation_size(conn,NULL,&sbuf);
953 mdate = sbuf.st_mtime;
954 adate = sbuf.st_atime;
955 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
957 if (lp_dos_filetime_resolution(SNUM(conn))) {
964 /* This is necessary, as otherwise the
965 * desktop.ini file in this folder is
967 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
971 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
977 mangle_map(fname,False,True,SNUM(conn));
982 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
984 switch (info_level) {
985 case SMB_FIND_INFO_STANDARD:
986 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
987 if(requires_resume_key) {
991 put_dos_date2(p,l1_fdateCreation,cdate);
992 put_dos_date2(p,l1_fdateLastAccess,adate);
993 put_dos_date2(p,l1_fdateLastWrite,mdate);
994 SIVAL(p,l1_cbFile,(uint32)file_size);
995 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
996 SSVAL(p,l1_attrFile,mode);
999 p += align_string(outbuf, p, 0);
1000 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1001 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1003 SCVAL(nameptr, -1, len - 2);
1005 SCVAL(nameptr, -1, 0);
1009 SCVAL(nameptr, -1, len - 1);
1011 SCVAL(nameptr, -1, 0);
1017 case SMB_FIND_EA_SIZE:
1018 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1019 if(requires_resume_key) {
1023 put_dos_date2(p,l2_fdateCreation,cdate);
1024 put_dos_date2(p,l2_fdateLastAccess,adate);
1025 put_dos_date2(p,l2_fdateLastWrite,mdate);
1026 SIVAL(p,l2_cbFile,(uint32)file_size);
1027 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1028 SSVAL(p,l2_attrFile,mode);
1030 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1031 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1035 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1036 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1049 SCVAL(nameptr,0,len);
1051 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1055 case SMB_FIND_EA_LIST:
1056 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1057 if(requires_resume_key) {
1063 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1064 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1065 was_8_3 = mangle_is_8_3(fname, True);
1067 SIVAL(p,0,reskey); p += 4;
1068 put_long_date(p,cdate); p += 8;
1069 put_long_date(p,adate); p += 8;
1070 put_long_date(p,mdate); p += 8;
1071 put_long_date(p,mdate); p += 8;
1072 SOFF_T(p,0,file_size); p += 8;
1073 SOFF_T(p,0,allocation_size); p += 8;
1074 SIVAL(p,0,nt_extmode); p += 4;
1075 q = p; p += 4; /* q is placeholder for name length. */
1077 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1078 SIVAL(p,0,ea_size); /* Extended attributes */
1081 /* Clear the short name buffer. This is
1082 * IMPORTANT as not doing so will trigger
1083 * a Win2k client bug. JRA.
1086 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1087 pstring mangled_name;
1088 pstrcpy(mangled_name, fname);
1089 mangle_map(mangled_name,True,True,SNUM(conn));
1090 mangled_name[12] = 0;
1091 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
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_DIRECTORY_INFO:
1108 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1110 SIVAL(p,0,reskey); p += 4;
1111 put_long_date(p,cdate); p += 8;
1112 put_long_date(p,adate); p += 8;
1113 put_long_date(p,mdate); p += 8;
1114 put_long_date(p,mdate); p += 8;
1115 SOFF_T(p,0,file_size); p += 8;
1116 SOFF_T(p,0,allocation_size); p += 8;
1117 SIVAL(p,0,nt_extmode); p += 4;
1118 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1121 len = PTR_DIFF(p, pdata);
1122 len = (len + 3) & ~3;
1127 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1128 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1130 SIVAL(p,0,reskey); p += 4;
1131 put_long_date(p,cdate); p += 8;
1132 put_long_date(p,adate); p += 8;
1133 put_long_date(p,mdate); p += 8;
1134 put_long_date(p,mdate); p += 8;
1135 SOFF_T(p,0,file_size); p += 8;
1136 SOFF_T(p,0,allocation_size); p += 8;
1137 SIVAL(p,0,nt_extmode); p += 4;
1138 q = p; p += 4; /* q is placeholder for name length. */
1140 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1141 SIVAL(p,0,ea_size); /* Extended attributes */
1144 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1148 len = PTR_DIFF(p, pdata);
1149 len = (len + 3) & ~3;
1154 case SMB_FIND_FILE_NAMES_INFO:
1155 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1157 SIVAL(p,0,reskey); p += 4;
1159 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1160 acl on a dir (tridge) */
1161 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1164 len = PTR_DIFF(p, pdata);
1165 len = (len + 3) & ~3;
1170 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1171 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1173 SIVAL(p,0,reskey); p += 4;
1174 put_long_date(p,cdate); p += 8;
1175 put_long_date(p,adate); p += 8;
1176 put_long_date(p,mdate); p += 8;
1177 put_long_date(p,mdate); p += 8;
1178 SOFF_T(p,0,file_size); p += 8;
1179 SOFF_T(p,0,allocation_size); p += 8;
1180 SIVAL(p,0,nt_extmode); p += 4;
1181 q = p; p += 4; /* q is placeholder for name length. */
1183 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1184 SIVAL(p,0,ea_size); /* Extended attributes */
1187 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1188 SIVAL(p,0,sbuf.st_dev); p += 4;
1189 SIVAL(p,0,sbuf.st_ino); p += 4;
1190 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1193 len = PTR_DIFF(p, pdata);
1194 len = (len + 3) & ~3;
1199 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1200 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1201 was_8_3 = mangle_is_8_3(fname, True);
1203 SIVAL(p,0,reskey); p += 4;
1204 put_long_date(p,cdate); p += 8;
1205 put_long_date(p,adate); p += 8;
1206 put_long_date(p,mdate); p += 8;
1207 put_long_date(p,mdate); p += 8;
1208 SOFF_T(p,0,file_size); p += 8;
1209 SOFF_T(p,0,allocation_size); p += 8;
1210 SIVAL(p,0,nt_extmode); p += 4;
1211 q = p; p += 4; /* q is placeholder for name length */
1213 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1214 SIVAL(p,0,ea_size); /* Extended attributes */
1217 /* Clear the short name buffer. This is
1218 * IMPORTANT as not doing so will trigger
1219 * a Win2k client bug. JRA.
1222 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1223 pstring mangled_name;
1224 pstrcpy(mangled_name, fname);
1225 mangle_map(mangled_name,True,True,SNUM(conn));
1226 mangled_name[12] = 0;
1227 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1234 SSVAL(p,0,0); p += 2; /* Reserved ? */
1235 SIVAL(p,0,sbuf.st_dev); p += 4;
1236 SIVAL(p,0,sbuf.st_ino); p += 4;
1237 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1240 len = PTR_DIFF(p, pdata);
1241 len = (len + 3) & ~3;
1246 /* CIFS UNIX Extension. */
1248 case SMB_FIND_FILE_UNIX:
1249 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1251 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1253 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1254 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1257 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1260 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1261 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1262 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1265 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1269 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1273 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1276 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1280 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1284 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1287 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1291 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1295 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1298 len = PTR_DIFF(p, pdata);
1299 len = (len + 3) & ~3;
1300 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1302 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1311 if (PTR_DIFF(p,pdata) > space_remaining) {
1312 /* Move the dirptr back to prev_dirpos */
1313 dptr_SeekDir(conn->dirptr, prev_dirpos);
1314 *out_of_space = True;
1315 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1316 return False; /* Not finished - just out of space */
1319 /* Setup the last entry pointer, as an offset from base_data */
1320 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1321 /* Advance the data pointer to the next slot */
1327 /****************************************************************************
1328 Reply to a TRANS2_FINDFIRST.
1329 ****************************************************************************/
1331 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1332 char **pparams, int total_params, char **ppdata, int total_data,
1333 unsigned int max_data_bytes)
1335 /* We must be careful here that we don't return more than the
1336 allowed number of data bytes. If this means returning fewer than
1337 maxentries then so be it. We assume that the redirector has
1338 enough room for the fixed number of parameter bytes it has
1340 char *params = *pparams;
1341 char *pdata = *ppdata;
1342 int dirtype = SVAL(params,0);
1343 int maxentries = SVAL(params,2);
1344 uint16 findfirst_flags = SVAL(params,4);
1345 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1346 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1347 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1348 int info_level = SVAL(params,6);
1352 int last_entry_off=0;
1356 BOOL finished = False;
1357 BOOL dont_descend = False;
1358 BOOL out_of_space = False;
1359 int space_remaining;
1360 BOOL bad_path = False;
1361 SMB_STRUCT_STAT sbuf;
1362 NTSTATUS ntstatus = NT_STATUS_OK;
1364 if (total_params < 12)
1365 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1367 *directory = *mask = 0;
1369 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1370 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1371 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1372 info_level, max_data_bytes));
1375 /* W2K3 seems to treat zero as 1. */
1379 switch (info_level) {
1380 case SMB_FIND_INFO_STANDARD:
1381 case SMB_FIND_EA_SIZE:
1382 case SMB_FIND_FILE_DIRECTORY_INFO:
1383 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1384 case SMB_FIND_FILE_NAMES_INFO:
1385 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1386 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1387 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1389 case SMB_FIND_FILE_UNIX:
1390 if (!lp_unix_extensions())
1391 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1394 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1397 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1398 if (!NT_STATUS_IS_OK(ntstatus)) {
1399 return ERROR_NT(ntstatus);
1402 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1404 unix_convert(directory,conn,0,&bad_path,&sbuf);
1406 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1408 if(!check_name(directory,conn)) {
1409 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1412 p = strrchr_m(directory,'/');
1414 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1415 if((directory[0] == '.') && (directory[1] == '\0'))
1418 pstrcpy(mask,directory);
1419 pstrcpy(directory,"./");
1425 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1427 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1429 return(ERROR_DOS(ERRDOS,ERRnomem));
1432 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1434 /* Realloc the params space */
1435 params = SMB_REALLOC(*pparams, 10);
1437 return ERROR_DOS(ERRDOS,ERRnomem);
1440 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1442 return(UNIXERROR(ERRDOS,ERRbadfile));
1444 /* Save the wildcard match and attribs we are using on this directory -
1445 needed as lanman2 assumes these are being saved between calls */
1447 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1448 dptr_close(&dptr_num);
1449 return ERROR_DOS(ERRDOS,ERRnomem);
1452 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1454 /* We don't need to check for VOL here as this is returned by
1455 a different TRANS2 call. */
1457 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1458 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1459 dont_descend = True;
1462 space_remaining = max_data_bytes;
1463 out_of_space = False;
1465 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1466 BOOL got_exact_match = False;
1468 /* this is a heuristic to avoid seeking the dirptr except when
1469 absolutely necessary. It allows for a filename of about 40 chars */
1470 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1471 out_of_space = True;
1474 finished = !get_lanman2_dir_entry(conn,
1476 mask,dirtype,info_level,
1477 requires_resume_key,dont_descend,
1478 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1482 if (finished && out_of_space)
1485 if (!finished && !out_of_space)
1489 * As an optimisation if we know we aren't looking
1490 * for a wildcard name (ie. the name matches the wildcard exactly)
1491 * then we can finish on any (first) match.
1492 * This speeds up large directory searches. JRA.
1498 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1501 /* Check if we can close the dirptr */
1502 if(close_after_first || (finished && close_if_end)) {
1503 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1504 dptr_close(&dptr_num);
1508 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1509 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1510 * the protocol level is less than NT1. Tested with smbclient. JRA.
1511 * This should fix the OS/2 client bug #2335.
1514 if(numentries == 0) {
1515 dptr_close(&dptr_num);
1516 if (Protocol < PROTOCOL_NT1) {
1517 return ERROR_DOS(ERRDOS,ERRnofiles);
1519 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1523 /* At this point pdata points to numentries directory entries. */
1525 /* Set up the return parameter block */
1526 SSVAL(params,0,dptr_num);
1527 SSVAL(params,2,numentries);
1528 SSVAL(params,4,finished);
1529 SSVAL(params,6,0); /* Never an EA error */
1530 SSVAL(params,8,last_entry_off);
1532 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1534 if ((! *directory) && dptr_path(dptr_num))
1535 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1537 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1538 smb_fn_name(CVAL(inbuf,smb_com)),
1539 mask, directory, dirtype, numentries ) );
1542 * Force a name mangle here to ensure that the
1543 * mask as an 8.3 name is top of the mangled cache.
1544 * The reasons for this are subtle. Don't remove
1545 * this code unless you know what you are doing
1546 * (see PR#13758). JRA.
1549 if(!mangle_is_8_3_wildcards( mask, False))
1550 mangle_map(mask, True, True, SNUM(conn));
1555 /****************************************************************************
1556 Reply to a TRANS2_FINDNEXT.
1557 ****************************************************************************/
1559 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1560 char **pparams, int total_params, char **ppdata, int total_data,
1561 unsigned int max_data_bytes)
1563 /* We must be careful here that we don't return more than the
1564 allowed number of data bytes. If this means returning fewer than
1565 maxentries then so be it. We assume that the redirector has
1566 enough room for the fixed number of parameter bytes it has
1568 char *params = *pparams;
1569 char *pdata = *ppdata;
1570 int dptr_num = SVAL(params,0);
1571 int maxentries = SVAL(params,2);
1572 uint16 info_level = SVAL(params,4);
1573 uint32 resume_key = IVAL(params,6);
1574 uint16 findnext_flags = SVAL(params,10);
1575 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1576 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1577 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1578 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1579 pstring resume_name;
1585 int i, last_entry_off=0;
1586 BOOL finished = False;
1587 BOOL dont_descend = False;
1588 BOOL out_of_space = False;
1589 int space_remaining;
1590 NTSTATUS ntstatus = NT_STATUS_OK;
1592 if (total_params < 12)
1593 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1595 *mask = *directory = *resume_name = 0;
1597 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1598 if (!NT_STATUS_IS_OK(ntstatus)) {
1599 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1600 complain (it thinks we're asking for the directory above the shared
1601 path or an invalid name). Catch this as the resume name is only compared, never used in
1602 a file access. JRA. */
1603 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1604 pstrcpy(resume_name, "..");
1605 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1606 pstrcpy(resume_name, ".");
1608 return ERROR_NT(ntstatus);
1612 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1613 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1614 resume_key = %d resume name = %s continue=%d level = %d\n",
1615 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1616 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1619 /* W2K3 seems to treat zero as 1. */
1623 switch (info_level) {
1624 case SMB_FIND_INFO_STANDARD:
1625 case SMB_FIND_EA_SIZE:
1626 case SMB_FIND_FILE_DIRECTORY_INFO:
1627 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1628 case SMB_FIND_FILE_NAMES_INFO:
1629 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1631 case SMB_FIND_FILE_UNIX:
1632 if (!lp_unix_extensions())
1633 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1636 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1639 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1641 return ERROR_DOS(ERRDOS,ERRnomem);
1644 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1646 /* Realloc the params space */
1647 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1648 if( params == NULL )
1649 return ERROR_DOS(ERRDOS,ERRnomem);
1653 /* Check that the dptr is valid */
1654 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1655 return ERROR_DOS(ERRDOS,ERRnofiles);
1657 string_set(&conn->dirpath,dptr_path(dptr_num));
1659 /* Get the wildcard mask from the dptr */
1660 if((p = dptr_wcard(dptr_num))== NULL) {
1661 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1662 return ERROR_DOS(ERRDOS,ERRnofiles);
1666 pstrcpy(directory,conn->dirpath);
1668 /* Get the attr mask from the dptr */
1669 dirtype = dptr_attr(dptr_num);
1671 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1672 dptr_num, mask, dirtype,
1674 dptr_TellDir(conn->dirptr)));
1676 /* We don't need to check for VOL here as this is returned by
1677 a different TRANS2 call. */
1679 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1680 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1681 dont_descend = True;
1684 space_remaining = max_data_bytes;
1685 out_of_space = False;
1688 * Seek to the correct position. We no longer use the resume key but
1689 * depend on the last file name instead.
1692 if(*resume_name && !continue_bit) {
1695 long current_pos = 0;
1697 * Remember, mangle_map is called by
1698 * get_lanman2_dir_entry(), so the resume name
1699 * could be mangled. Ensure we check the unmangled name.
1702 if (mangle_is_mangled(resume_name)) {
1703 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1707 * Fix for NT redirector problem triggered by resume key indexes
1708 * changing between directory scans. We now return a resume key of 0
1709 * and instead look for the filename to continue from (also given
1710 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1711 * findfirst/findnext (as is usual) then the directory pointer
1712 * should already be at the correct place.
1715 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
1716 } /* end if resume_name && !continue_bit */
1718 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1719 BOOL got_exact_match = False;
1721 /* this is a heuristic to avoid seeking the dirptr except when
1722 absolutely necessary. It allows for a filename of about 40 chars */
1723 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1724 out_of_space = True;
1727 finished = !get_lanman2_dir_entry(conn,
1729 mask,dirtype,info_level,
1730 requires_resume_key,dont_descend,
1731 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1735 if (finished && out_of_space)
1738 if (!finished && !out_of_space)
1742 * As an optimisation if we know we aren't looking
1743 * for a wildcard name (ie. the name matches the wildcard exactly)
1744 * then we can finish on any (first) match.
1745 * This speeds up large directory searches. JRA.
1751 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1754 /* Check if we can close the dirptr */
1755 if(close_after_request || (finished && close_if_end)) {
1756 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1757 dptr_close(&dptr_num); /* This frees up the saved mask */
1760 /* Set up the return parameter block */
1761 SSVAL(params,0,numentries);
1762 SSVAL(params,2,finished);
1763 SSVAL(params,4,0); /* Never an EA error */
1764 SSVAL(params,6,last_entry_off);
1766 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1768 if ((! *directory) && dptr_path(dptr_num))
1769 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1771 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1772 smb_fn_name(CVAL(inbuf,smb_com)),
1773 mask, directory, dirtype, numentries ) );
1778 /****************************************************************************
1779 Reply to a TRANS2_QFSINFO (query filesystem info).
1780 ****************************************************************************/
1782 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1783 char **pparams, int total_params, char **ppdata, int total_data,
1784 unsigned int max_data_bytes)
1786 char *pdata = *ppdata;
1787 char *params = *pparams;
1788 uint16 info_level = SVAL(params,0);
1791 char *vname = volume_label(SNUM(conn));
1792 int snum = SNUM(conn);
1793 char *fstype = lp_fstype(SNUM(conn));
1796 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1798 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1799 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1800 return ERROR_DOS(ERRSRV,ERRinvdevice);
1803 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1804 if ( pdata == NULL )
1805 return ERROR_DOS(ERRDOS,ERRnomem);
1808 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1810 switch (info_level) {
1811 case SMB_INFO_ALLOCATION:
1813 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1815 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1816 return(UNIXERROR(ERRHRD,ERRgeneral));
1819 block_size = lp_block_size(snum);
1820 if (bsize < block_size) {
1821 SMB_BIG_UINT factor = block_size/bsize;
1826 if (bsize > block_size) {
1827 SMB_BIG_UINT factor = bsize/block_size;
1832 bytes_per_sector = 512;
1833 sectors_per_unit = bsize/bytes_per_sector;
1835 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1836 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1837 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1839 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1840 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1841 SIVAL(pdata,l1_cUnit,dsize);
1842 SIVAL(pdata,l1_cUnitAvail,dfree);
1843 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1847 case SMB_INFO_VOLUME:
1848 /* Return volume name */
1850 * Add volume serial number - hash of a combination of
1851 * the called hostname and the service name.
1853 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1854 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1855 SCVAL(pdata,l2_vol_cch,len);
1856 data_len = l2_vol_szVolLabel + len;
1857 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1858 (unsigned)st.st_ctime, len, vname));
1861 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1862 case SMB_FS_ATTRIBUTE_INFORMATION:
1865 #if defined(HAVE_SYS_QUOTAS)
1866 quota_flag = FILE_VOLUME_QUOTAS;
1869 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1870 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1871 quota_flag); /* FS ATTRIBUTES */
1873 SIVAL(pdata,4,255); /* Max filename component length */
1874 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1875 and will think we can't do long filenames */
1876 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1878 data_len = 12 + len;
1881 case SMB_QUERY_FS_LABEL_INFO:
1882 case SMB_FS_LABEL_INFORMATION:
1883 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1888 case SMB_QUERY_FS_VOLUME_INFO:
1889 case SMB_FS_VOLUME_INFORMATION:
1892 * Add volume serial number - hash of a combination of
1893 * the called hostname and the service name.
1895 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1896 (str_checksum(get_local_machine_name())<<16));
1898 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1899 SIVAL(pdata,12,len);
1901 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1902 (int)strlen(vname),vname, lp_servicename(snum)));
1905 case SMB_QUERY_FS_SIZE_INFO:
1906 case SMB_FS_SIZE_INFORMATION:
1908 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1910 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1911 return(UNIXERROR(ERRHRD,ERRgeneral));
1913 block_size = lp_block_size(snum);
1914 if (bsize < block_size) {
1915 SMB_BIG_UINT factor = block_size/bsize;
1920 if (bsize > block_size) {
1921 SMB_BIG_UINT factor = bsize/block_size;
1926 bytes_per_sector = 512;
1927 sectors_per_unit = bsize/bytes_per_sector;
1928 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1929 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1930 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1931 SBIG_UINT(pdata,0,dsize);
1932 SBIG_UINT(pdata,8,dfree);
1933 SIVAL(pdata,16,sectors_per_unit);
1934 SIVAL(pdata,20,bytes_per_sector);
1938 case SMB_FS_FULL_SIZE_INFORMATION:
1940 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1942 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1943 return(UNIXERROR(ERRHRD,ERRgeneral));
1945 block_size = lp_block_size(snum);
1946 if (bsize < block_size) {
1947 SMB_BIG_UINT factor = block_size/bsize;
1952 if (bsize > block_size) {
1953 SMB_BIG_UINT factor = bsize/block_size;
1958 bytes_per_sector = 512;
1959 sectors_per_unit = bsize/bytes_per_sector;
1960 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1962 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1963 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1964 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1965 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1966 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1967 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1971 case SMB_QUERY_FS_DEVICE_INFO:
1972 case SMB_FS_DEVICE_INFORMATION:
1974 SIVAL(pdata,0,0); /* dev type */
1975 SIVAL(pdata,4,0); /* characteristics */
1978 #ifdef HAVE_SYS_QUOTAS
1979 case SMB_FS_QUOTA_INFORMATION:
1981 * what we have to send --metze:
1983 * Unknown1: 24 NULL bytes
1984 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1985 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1986 * Quota Flags: 2 byte :
1987 * Unknown3: 6 NULL bytes
1991 * details for Quota Flags:
1993 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1994 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1995 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1996 * 0x0001 Enable Quotas: enable quota for this fs
2000 /* we need to fake up a fsp here,
2001 * because its not send in this call
2004 SMB_NTQUOTA_STRUCT quotas;
2007 ZERO_STRUCT(quotas);
2014 if (current_user.uid != 0) {
2015 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2016 lp_servicename(SNUM(conn)),conn->user));
2017 return ERROR_DOS(ERRDOS,ERRnoaccess);
2020 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2021 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2022 return ERROR_DOS(ERRSRV,ERRerror);
2027 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2029 /* Unknown1 24 NULL bytes*/
2030 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2031 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2032 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2034 /* Default Soft Quota 8 bytes */
2035 SBIG_UINT(pdata,24,quotas.softlim);
2037 /* Default Hard Quota 8 bytes */
2038 SBIG_UINT(pdata,32,quotas.hardlim);
2040 /* Quota flag 2 bytes */
2041 SSVAL(pdata,40,quotas.qflags);
2043 /* Unknown3 6 NULL bytes */
2049 #endif /* HAVE_SYS_QUOTAS */
2050 case SMB_FS_OBJECTID_INFORMATION:
2055 * Query the version and capabilities of the CIFS UNIX extensions
2059 case SMB_QUERY_CIFS_UNIX_INFO:
2060 if (!lp_unix_extensions())
2061 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2063 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2064 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2065 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2068 case SMB_MAC_QUERY_FS_INFO:
2070 * Thursby MAC extension... ONLY on NTFS filesystems
2071 * once we do streams then we don't need this
2073 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2075 SIVAL(pdata,84,0x100); /* Don't support mac... */
2080 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2084 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2086 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2091 #ifdef HAVE_SYS_QUOTAS
2092 /****************************************************************************
2093 Reply to a TRANS2_SETFSINFO (set filesystem info).
2094 ****************************************************************************/
2096 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2097 char **pparams, int total_params, char **ppdata, int total_data,
2098 unsigned int max_data_bytes)
2100 char *pdata = *ppdata;
2101 char *params = *pparams;
2102 files_struct *fsp = NULL;
2105 SMB_NTQUOTA_STRUCT quotas;
2107 ZERO_STRUCT(quotas);
2109 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2112 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2113 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2114 lp_servicename(SNUM(conn)),conn->user));
2115 return ERROR_DOS(ERRSRV,ERRaccess);
2119 if (total_params < 4) {
2120 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2122 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2125 fsp = file_fsp(params,0);
2127 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2128 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2129 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2132 info_level = SVAL(params,2);
2134 switch(info_level) {
2135 case SMB_FS_QUOTA_INFORMATION:
2136 /* note: normaly there're 48 bytes,
2137 * but we didn't use the last 6 bytes for now
2140 if (total_data < 42) {
2141 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2143 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2146 /* unknown_1 24 NULL bytes in pdata*/
2148 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2149 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2150 #ifdef LARGE_SMB_OFF_T
2151 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2152 #else /* LARGE_SMB_OFF_T */
2153 if ((IVAL(pdata,28) != 0)&&
2154 ((quotas.softlim != 0xFFFFFFFF)||
2155 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2156 /* more than 32 bits? */
2157 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2159 #endif /* LARGE_SMB_OFF_T */
2161 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2162 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2163 #ifdef LARGE_SMB_OFF_T
2164 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2165 #else /* LARGE_SMB_OFF_T */
2166 if ((IVAL(pdata,36) != 0)&&
2167 ((quotas.hardlim != 0xFFFFFFFF)||
2168 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2169 /* more than 32 bits? */
2170 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2172 #endif /* LARGE_SMB_OFF_T */
2174 /* quota_flags 2 bytes **/
2175 quotas.qflags = SVAL(pdata,40);
2177 /* unknown_2 6 NULL bytes follow*/
2179 /* now set the quotas */
2180 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2181 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2182 return ERROR_DOS(ERRSRV,ERRerror);
2187 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2189 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2194 * sending this reply works fine,
2195 * but I'm not sure it's the same
2196 * like windows do...
2199 outsize = set_message(outbuf,10,0,True);
2203 #endif /* HAVE_SYS_QUOTAS */
2205 /****************************************************************************
2206 Utility function to set bad path error.
2207 ****************************************************************************/
2209 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2211 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2212 err, (int)bad_path ));
2216 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2218 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2221 return UNIXERROR(def_class,def_code);
2224 #if defined(HAVE_POSIX_ACLS)
2225 /****************************************************************************
2226 Utility function to count the number of entries in a POSIX acl.
2227 ****************************************************************************/
2229 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2231 unsigned int ace_count = 0;
2232 int entry_id = SMB_ACL_FIRST_ENTRY;
2233 SMB_ACL_ENTRY_T entry;
2235 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2237 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2238 entry_id = SMB_ACL_NEXT_ENTRY;
2245 /****************************************************************************
2246 Utility function to marshall a POSIX acl into wire format.
2247 ****************************************************************************/
2249 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2251 int entry_id = SMB_ACL_FIRST_ENTRY;
2252 SMB_ACL_ENTRY_T entry;
2254 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2255 SMB_ACL_TAG_T tagtype;
2256 SMB_ACL_PERMSET_T permset;
2257 unsigned char perms = 0;
2258 unsigned int own_grp;
2261 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2262 entry_id = SMB_ACL_NEXT_ENTRY;
2265 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2266 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2270 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2271 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2275 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2276 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2277 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2279 SCVAL(pdata,1,perms);
2282 case SMB_ACL_USER_OBJ:
2283 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2284 own_grp = (unsigned int)pst->st_uid;
2285 SIVAL(pdata,2,own_grp);
2290 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2292 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2294 own_grp = (unsigned int)*puid;
2295 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2296 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2297 SIVAL(pdata,2,own_grp);
2301 case SMB_ACL_GROUP_OBJ:
2302 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2303 own_grp = (unsigned int)pst->st_gid;
2304 SIVAL(pdata,2,own_grp);
2309 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2311 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2313 own_grp = (unsigned int)*pgid;
2314 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2315 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2316 SIVAL(pdata,2,own_grp);
2321 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2322 SIVAL(pdata,2,0xFFFFFFFF);
2323 SIVAL(pdata,6,0xFFFFFFFF);
2326 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2327 SIVAL(pdata,2,0xFFFFFFFF);
2328 SIVAL(pdata,6,0xFFFFFFFF);
2331 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2334 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2341 /****************************************************************************
2342 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2343 file name or file id).
2344 ****************************************************************************/
2346 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2347 char **pparams, int total_params, char **ppdata, int total_data,
2348 unsigned int max_data_bytes)
2350 char *params = *pparams;
2351 char *pdata = *ppdata;
2352 uint16 tran_call = SVAL(inbuf, smb_setup0);
2355 SMB_OFF_T file_size=0;
2356 SMB_BIG_UINT allocation_size=0;
2357 unsigned int data_size = 0;
2358 unsigned int param_size = 2;
2359 SMB_STRUCT_STAT sbuf;
2360 pstring fname, dos_fname;
2365 BOOL bad_path = False;
2366 BOOL delete_pending = False;
2369 files_struct *fsp = NULL;
2370 TALLOC_CTX *ea_ctx = NULL;
2371 struct ea_list *ea_list = NULL;
2372 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2375 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2379 if (tran_call == TRANSACT2_QFILEINFO) {
2380 if (total_params < 4)
2381 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2383 fsp = file_fsp(params,0);
2384 info_level = SVAL(params,2);
2386 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2388 if(fsp && (fsp->fake_file_handle)) {
2390 * This is actually for the QUOTA_FAKE_FILE --metze
2393 pstrcpy(fname, fsp->fsp_name);
2394 /* We know this name is ok, it's already passed the checks. */
2396 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2398 * This is actually a QFILEINFO on a directory
2399 * handle (returned from an NT SMB). NT5.0 seems
2400 * to do this call. JRA.
2402 /* We know this name is ok, it's already passed the checks. */
2403 pstrcpy(fname, fsp->fsp_name);
2405 if (INFO_LEVEL_IS_UNIX(info_level)) {
2406 /* Always do lstat for UNIX calls. */
2407 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2408 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2409 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2411 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2412 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2413 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2416 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2419 * Original code - this is an open file.
2421 CHECK_FSP(fsp,conn);
2423 pstrcpy(fname, fsp->fsp_name);
2424 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2425 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2426 return(UNIXERROR(ERRDOS,ERRbadfid));
2428 pos = fsp->position_information;
2429 delete_pending = fsp->delete_on_close;
2430 desired_access = fsp->desired_access;
2433 NTSTATUS status = NT_STATUS_OK;
2436 if (total_params < 6)
2437 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2439 info_level = SVAL(params,0);
2441 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2443 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 return ERROR_NT(status);
2448 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2450 unix_convert(fname,conn,0,&bad_path,&sbuf);
2452 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2454 if (!check_name(fname,conn)) {
2455 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2456 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2459 if (INFO_LEVEL_IS_UNIX(info_level)) {
2460 /* Always do lstat for UNIX calls. */
2461 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2462 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2463 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2465 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2466 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2467 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2471 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2472 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2474 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2475 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2477 p = strrchr_m(fname,'/');
2483 mode = dos_mode(conn,fname,&sbuf);
2485 mode = FILE_ATTRIBUTE_NORMAL;
2487 fullpathname = fname;
2488 file_size = get_file_size(sbuf);
2489 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2491 /* This is necessary, as otherwise the desktop.ini file in
2492 * this folder is ignored */
2493 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2497 /* Pull any EA list from the data portion. */
2498 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2499 uint32 ea_size = IVAL(pdata,0);
2501 if (total_data > 0 && ea_size != total_data) {
2502 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2503 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2504 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2507 if (!lp_ea_support(SNUM(conn))) {
2508 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2511 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2512 return ERROR_NT(NT_STATUS_NO_MEMORY);
2515 /* Pull out the list of names. */
2516 ea_list = read_ea_list(ea_ctx, pdata, ea_size);
2518 talloc_destroy(ea_ctx);
2519 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2523 params = SMB_REALLOC(*pparams,2);
2524 if (params == NULL) {
2525 talloc_destroy(ea_ctx);
2526 return ERROR_NT(NT_STATUS_NO_MEMORY);
2529 memset((char *)params,'\0',2);
2530 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2531 pdata = SMB_REALLOC(*ppdata, data_size);
2532 if ( pdata == NULL ) {
2533 talloc_destroy(ea_ctx);
2534 return ERROR_NT(NT_STATUS_NO_MEMORY);
2538 memset((char *)pdata,'\0',data_size);
2540 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2543 if (fsp->pending_modtime) {
2544 /* the pending modtime overrides the current modtime */
2545 sbuf.st_mtime = fsp->pending_modtime;
2548 /* Do we have this path open ? */
2549 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2550 if (fsp1 && fsp1->pending_modtime) {
2551 /* the pending modtime overrides the current modtime */
2552 sbuf.st_mtime = fsp1->pending_modtime;
2556 if (lp_dos_filetime_resolution(SNUM(conn))) {
2558 sbuf.st_atime &= ~1;
2559 sbuf.st_ctime &= ~1;
2560 sbuf.st_mtime &= ~1;
2563 /* NT expects the name to be in an exact form of the *full*
2564 filename. See the trans2 torture test */
2565 if (strequal(base_name,".")) {
2566 pstrcpy(dos_fname, "\\");
2568 pstr_sprintf(dos_fname, "\\%s", fname);
2569 string_replace(dos_fname, '/', '\\');
2572 switch (info_level) {
2573 case SMB_INFO_STANDARD:
2574 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2576 put_dos_date2(pdata,l1_fdateCreation,c_time);
2577 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2578 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2579 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2580 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2581 SSVAL(pdata,l1_attrFile,mode);
2584 case SMB_INFO_QUERY_EA_SIZE:
2586 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2587 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2589 put_dos_date2(pdata,l1_fdateCreation,c_time);
2590 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2591 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2592 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2593 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2594 SSVAL(pdata,l1_attrFile,mode);
2595 SIVAL(pdata,l1_attrFile+2,ea_size);
2599 case SMB_INFO_IS_NAME_VALID:
2600 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2601 if (tran_call == TRANSACT2_QFILEINFO) {
2602 /* os/2 needs this ? really ?*/
2603 return ERROR_DOS(ERRDOS,ERRbadfunc);
2609 case SMB_INFO_QUERY_EAS_FROM_LIST:
2611 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2613 put_dos_date2(pdata,0,c_time);
2614 put_dos_date2(pdata,4,sbuf.st_atime);
2615 put_dos_date2(pdata,8,sbuf.st_mtime);
2616 SIVAL(pdata,12,(uint32)file_size);
2617 SIVAL(pdata,16,(uint32)allocation_size);
2618 SIVAL(pdata,20,mode);
2619 talloc_destroy(ea_ctx);
2623 case SMB_INFO_QUERY_ALL_EAS:
2625 /* We have data_size bytes to put EA's into. */
2626 size_t total_ea_len = 0;
2628 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2630 ea_ctx = talloc_init("ea_ctx");
2632 return ERROR_NT(NT_STATUS_NO_MEMORY);
2635 ea_list = get_ea_list(ea_ctx, conn, fsp, fname, &total_ea_len);
2636 if (!ea_list || (total_ea_len > data_size)) {
2637 talloc_destroy(ea_ctx);
2642 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2643 talloc_destroy(ea_ctx);
2647 case SMB_FILE_BASIC_INFORMATION:
2648 case SMB_QUERY_FILE_BASIC_INFO:
2650 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2651 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2652 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2654 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2658 put_long_date(pdata,c_time);
2659 put_long_date(pdata+8,sbuf.st_atime);
2660 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2661 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2662 SIVAL(pdata,32,mode);
2664 DEBUG(5,("SMB_QFBI - "));
2666 time_t create_time = c_time;
2667 DEBUG(5,("create: %s ", ctime(&create_time)));
2669 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2670 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2671 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2672 DEBUG(5,("mode: %x\n", mode));
2676 case SMB_FILE_STANDARD_INFORMATION:
2677 case SMB_QUERY_FILE_STANDARD_INFO:
2679 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2681 SOFF_T(pdata,0,allocation_size);
2682 SOFF_T(pdata,8,file_size);
2683 if (delete_pending & sbuf.st_nlink)
2684 SIVAL(pdata,16,sbuf.st_nlink - 1);
2686 SIVAL(pdata,16,sbuf.st_nlink);
2688 SCVAL(pdata,21,(mode&aDIR)?1:0);
2691 case SMB_FILE_EA_INFORMATION:
2692 case SMB_QUERY_FILE_EA_INFO:
2694 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2695 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2697 SIVAL(pdata,0,ea_size);
2701 /* Get the 8.3 name - used if NT SMB was negotiated. */
2702 case SMB_QUERY_FILE_ALT_NAME_INFO:
2703 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2708 pstrcpy(short_name,base_name);
2709 /* Mangle if not already 8.3 */
2710 if(!mangle_is_8_3(short_name, True)) {
2711 mangle_map(short_name,True,True,SNUM(conn));
2713 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2714 data_size = 4 + len;
2719 case SMB_QUERY_FILE_NAME_INFO:
2721 this must be *exactly* right for ACLs on mapped drives to work
2723 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2724 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2725 data_size = 4 + len;
2729 case SMB_FILE_ALLOCATION_INFORMATION:
2730 case SMB_QUERY_FILE_ALLOCATION_INFO:
2731 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2733 SOFF_T(pdata,0,allocation_size);
2736 case SMB_FILE_END_OF_FILE_INFORMATION:
2737 case SMB_QUERY_FILE_END_OF_FILEINFO:
2738 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2740 SOFF_T(pdata,0,file_size);
2743 case SMB_QUERY_FILE_ALL_INFO:
2744 case SMB_FILE_ALL_INFORMATION:
2746 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2747 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2748 put_long_date(pdata,c_time);
2749 put_long_date(pdata+8,sbuf.st_atime);
2750 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2751 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2752 SIVAL(pdata,32,mode);
2754 SOFF_T(pdata,0,allocation_size);
2755 SOFF_T(pdata,8,file_size);
2756 if (delete_pending && sbuf.st_nlink)
2757 SIVAL(pdata,16,sbuf.st_nlink - 1);
2759 SIVAL(pdata,16,sbuf.st_nlink);
2760 SCVAL(pdata,20,delete_pending);
2761 SCVAL(pdata,21,(mode&aDIR)?1:0);
2763 SIVAL(pdata,0,ea_size);
2764 pdata += 4; /* EA info */
2765 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2768 data_size = PTR_DIFF(pdata,(*ppdata));
2771 case SMB_FILE_INTERNAL_INFORMATION:
2772 /* This should be an index number - looks like
2775 I think this causes us to fail the IFSKIT
2776 BasicFileInformationTest. -tpot */
2778 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2779 SIVAL(pdata,0,sbuf.st_dev);
2780 SIVAL(pdata,4,sbuf.st_ino);
2784 case SMB_FILE_ACCESS_INFORMATION:
2785 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2786 SIVAL(pdata,0,desired_access);
2790 case SMB_FILE_NAME_INFORMATION:
2791 /* Pathname with leading '\'. */
2794 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2795 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2796 SIVAL(pdata,0,byte_len);
2797 data_size = 4 + byte_len;
2801 case SMB_FILE_DISPOSITION_INFORMATION:
2802 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2804 SCVAL(pdata,0,delete_pending);
2807 case SMB_FILE_POSITION_INFORMATION:
2808 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2810 SOFF_T(pdata,0,pos);
2813 case SMB_FILE_MODE_INFORMATION:
2814 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2815 SIVAL(pdata,0,mode);
2819 case SMB_FILE_ALIGNMENT_INFORMATION:
2820 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2821 SIVAL(pdata,0,0); /* No alignment needed. */
2827 * NT4 server just returns "invalid query" to this - if we try to answer
2828 * it then NTws gets a BSOD! (tridge).
2829 * W2K seems to want this. JRA.
2831 case SMB_QUERY_FILE_STREAM_INFO:
2833 case SMB_FILE_STREAM_INFORMATION:
2834 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2838 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2839 SIVAL(pdata,0,0); /* ??? */
2840 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2841 SOFF_T(pdata,8,file_size);
2842 SIVAL(pdata,16,allocation_size);
2843 SIVAL(pdata,20,0); /* ??? */
2844 data_size = 24 + byte_len;
2848 case SMB_QUERY_COMPRESSION_INFO:
2849 case SMB_FILE_COMPRESSION_INFORMATION:
2850 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2851 SOFF_T(pdata,0,file_size);
2852 SIVAL(pdata,8,0); /* ??? */
2853 SIVAL(pdata,12,0); /* ??? */
2857 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2858 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2859 put_long_date(pdata,c_time);
2860 put_long_date(pdata+8,sbuf.st_atime);
2861 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2862 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2863 SIVAL(pdata,32,allocation_size);
2864 SOFF_T(pdata,40,file_size);
2865 SIVAL(pdata,48,mode);
2866 SIVAL(pdata,52,0); /* ??? */
2870 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2871 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2872 SIVAL(pdata,0,mode);
2878 * CIFS UNIX Extensions.
2881 case SMB_QUERY_FILE_UNIX_BASIC:
2883 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2884 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2886 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2889 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2892 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2893 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2894 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2897 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2901 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2905 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2908 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2912 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2916 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2919 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2923 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2926 data_size = PTR_DIFF(pdata,(*ppdata));
2930 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2932 for (i=0; i<100; i++)
2933 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2939 case SMB_QUERY_FILE_UNIX_LINK:
2943 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2945 if(!S_ISLNK(sbuf.st_mode))
2946 return(UNIXERROR(ERRSRV,ERRbadlink));
2948 return(UNIXERROR(ERRDOS,ERRbadlink));
2950 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2952 return(UNIXERROR(ERRDOS,ERRnoaccess));
2954 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2956 data_size = PTR_DIFF(pdata,(*ppdata));
2961 #if defined(HAVE_POSIX_ACLS)
2962 case SMB_QUERY_POSIX_ACL:
2964 SMB_ACL_T file_acl = NULL;
2965 SMB_ACL_T def_acl = NULL;
2966 uint16 num_file_acls = 0;
2967 uint16 num_def_acls = 0;
2969 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2970 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2972 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2975 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2976 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2978 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2981 if (S_ISDIR(sbuf.st_mode)) {
2982 if (fsp && fsp->is_directory) {
2983 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2985 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2987 def_acl = free_empty_sys_acl(conn, def_acl);
2990 num_file_acls = count_acl_entries(conn, file_acl);
2991 num_def_acls = count_acl_entries(conn, def_acl);
2993 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2994 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2996 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2997 SMB_POSIX_ACL_HEADER_SIZE) ));
2999 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3002 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3004 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3007 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3008 SSVAL(pdata,2,num_file_acls);
3009 SSVAL(pdata,4,num_def_acls);
3010 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3012 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3015 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3017 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3019 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3021 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3024 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3026 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3030 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3033 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3035 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3041 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3044 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3049 /****************************************************************************
3050 Deal with the internal needs of setting the delete on close flag. Note that
3051 as the tdb locking is recursive, it is safe to call this from within
3052 open_file_shared. JRA.
3053 ****************************************************************************/
3055 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3057 if (delete_on_close) {
3059 * Only allow delete on close for writable files.
3062 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3063 if (dosmode & aRONLY) {
3064 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3066 return NT_STATUS_CANNOT_DELETE;
3071 * Only allow delete on close for writable shares.
3074 if (!CAN_WRITE(fsp->conn)) {
3075 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3077 return NT_STATUS_ACCESS_DENIED;
3081 * Only allow delete on close for files/directories opened with delete intent.
3084 if (!(fsp->desired_access & DELETE_ACCESS)) {
3085 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3087 return NT_STATUS_ACCESS_DENIED;
3091 if(fsp->is_directory) {
3092 fsp->directory_delete_on_close = delete_on_close;
3093 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3094 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3096 fsp->delete_on_close = delete_on_close;
3097 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3098 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3101 return NT_STATUS_OK;
3104 /****************************************************************************
3105 Sets the delete on close flag over all share modes on this file.
3106 Modify the share mode entry for all files open
3107 on this device and inode to tell other smbds we have
3108 changed the delete on close flag. This will be noticed
3109 in the close code, the last closer will delete the file
3111 ****************************************************************************/
3113 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3115 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3116 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3118 if (fsp->is_directory || fsp->is_stat)
3119 return NT_STATUS_OK;
3121 if (lock_share_entry_fsp(fsp) == False)
3122 return NT_STATUS_ACCESS_DENIED;
3124 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3125 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3127 unlock_share_entry_fsp(fsp);
3128 return NT_STATUS_ACCESS_DENIED;
3131 unlock_share_entry_fsp(fsp);
3132 return NT_STATUS_OK;
3135 /****************************************************************************
3136 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3138 ****************************************************************************/
3140 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3142 BOOL bad_path_oldname = False;
3143 BOOL bad_path_newname = False;
3144 SMB_STRUCT_STAT sbuf1, sbuf2;
3145 pstring last_component_oldname;
3146 pstring last_component_newname;
3147 NTSTATUS status = NT_STATUS_OK;
3153 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3154 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3157 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3158 if (bad_path_oldname) {
3159 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3162 /* Quick check for "." and ".." */
3163 if (last_component_oldname[0] == '.') {
3164 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3165 return NT_STATUS_OBJECT_NAME_INVALID;
3169 /* source must already exist. */
3170 if (!VALID_STAT(sbuf1)) {
3171 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3174 if (!check_name(oldname,conn)) {
3175 return NT_STATUS_ACCESS_DENIED;
3178 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3179 if (bad_path_newname) {
3180 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3183 /* Quick check for "." and ".." */
3184 if (last_component_newname[0] == '.') {
3185 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3186 return NT_STATUS_OBJECT_NAME_INVALID;
3190 /* Disallow if newname already exists. */
3191 if (VALID_STAT(sbuf2)) {
3192 return NT_STATUS_OBJECT_NAME_COLLISION;
3195 if (!check_name(newname,conn)) {
3196 return NT_STATUS_ACCESS_DENIED;
3199 /* No links from a directory. */
3200 if (S_ISDIR(sbuf1.st_mode)) {
3201 return NT_STATUS_FILE_IS_A_DIRECTORY;
3204 /* Ensure this is within the share. */
3205 if (!reduce_name(conn, oldname) != 0)
3206 return NT_STATUS_ACCESS_DENIED;
3208 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3210 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3211 status = map_nt_error_from_unix(errno);
3212 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3213 nt_errstr(status), newname, oldname));
3219 /****************************************************************************
3220 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3221 ****************************************************************************/
3223 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3224 char **pparams, int total_params, char **ppdata, int total_data,
3225 unsigned int max_data_bytes)
3227 char *params = *pparams;
3228 char *pdata = *ppdata;
3229 uint16 tran_call = SVAL(inbuf, smb_setup0);
3234 SMB_STRUCT_STAT sbuf;
3237 BOOL bad_path = False;
3238 files_struct *fsp = NULL;
3239 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3240 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3241 mode_t unixmode = 0;
3242 NTSTATUS status = NT_STATUS_OK;
3245 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3249 if (tran_call == TRANSACT2_SETFILEINFO) {
3250 if (total_params < 4)
3251 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3253 fsp = file_fsp(params,0);
3254 info_level = SVAL(params,2);
3256 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3258 * This is actually a SETFILEINFO on a directory
3259 * handle (returned from an NT SMB). NT5.0 seems
3260 * to do this call. JRA.
3262 pstrcpy(fname, fsp->fsp_name);
3263 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3264 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3265 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3267 } else if (fsp && fsp->print_file) {
3269 * Doing a DELETE_ON_CLOSE should cancel a print job.
3271 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3272 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3274 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3277 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3280 return (UNIXERROR(ERRDOS,ERRbadpath));
3283 * Original code - this is an open file.
3285 CHECK_FSP(fsp,conn);
3287 pstrcpy(fname, fsp->fsp_name);
3290 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3291 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3292 return(UNIXERROR(ERRDOS,ERRbadfid));
3297 if (total_params < 6)
3298 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3300 info_level = SVAL(params,0);
3301 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 return ERROR_NT(status);
3305 unix_convert(fname,conn,0,&bad_path,&sbuf);
3307 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3311 * For CIFS UNIX extensions the target name may not exist.
3314 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3315 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3316 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3319 if(!check_name(fname, conn)) {
3320 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3325 if (!CAN_WRITE(conn))
3326 return ERROR_DOS(ERRSRV,ERRaccess);
3328 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3329 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3331 if (VALID_STAT(sbuf))
3332 unixmode = sbuf.st_mode;
3334 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3335 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3337 /* Realloc the parameter and data sizes */
3338 params = SMB_REALLOC(*pparams,2);
3340 return ERROR_DOS(ERRDOS,ERRnomem);
3345 if (fsp && fsp->pending_modtime) {
3346 /* the pending modtime overrides the current modtime */
3347 sbuf.st_mtime = fsp->pending_modtime;
3350 size = get_file_size(sbuf);
3351 tvs.modtime = sbuf.st_mtime;
3352 tvs.actime = sbuf.st_atime;
3353 dosmode = dos_mode(conn,fname,&sbuf);
3354 unixmode = sbuf.st_mode;
3356 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3357 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3359 switch (info_level) {
3360 case SMB_INFO_STANDARD:
3362 if (total_data < 12)
3363 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3366 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3368 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3372 case SMB_INFO_SET_EA:
3373 status = set_ea(conn, fsp, fname, pdata, total_data);
3374 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3375 return ERROR_NT(status);
3378 /* XXXX um, i don't think this is right.
3379 it's also not in the cifs6.txt spec.
3381 case SMB_INFO_QUERY_EAS_FROM_LIST:
3382 if (total_data < 28)
3383 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3385 tvs.actime = make_unix_date2(pdata+8);
3386 tvs.modtime = make_unix_date2(pdata+12);
3387 size = IVAL(pdata,16);
3388 dosmode = IVAL(pdata,24);
3391 /* XXXX nor this. not in cifs6.txt, either. */
3392 case SMB_INFO_QUERY_ALL_EAS:
3393 if (total_data < 28)
3394 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3396 tvs.actime = make_unix_date2(pdata+8);
3397 tvs.modtime = make_unix_date2(pdata+12);
3398 size = IVAL(pdata,16);
3399 dosmode = IVAL(pdata,24);
3402 case SMB_SET_FILE_BASIC_INFO:
3403 case SMB_FILE_BASIC_INFORMATION:
3405 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3407 time_t changed_time;
3409 if (total_data < 36)
3410 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3412 /* Ignore create time at offset pdata. */
3415 tvs.actime = interpret_long_date(pdata+8);
3417 write_time = interpret_long_date(pdata+16);
3418 changed_time = interpret_long_date(pdata+24);
3420 tvs.modtime = MIN(write_time, changed_time);
3422 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3423 tvs.modtime = write_time;
3425 /* Prefer a defined time to an undefined one. */
3426 if (null_mtime(tvs.modtime)) {
3427 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3431 dosmode = IVAL(pdata,32);
3435 case SMB_FILE_ALLOCATION_INFORMATION:
3436 case SMB_SET_FILE_ALLOCATION_INFO:
3439 SMB_BIG_UINT allocation_size;
3442 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3444 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3445 #ifdef LARGE_SMB_OFF_T
3446 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3447 #else /* LARGE_SMB_OFF_T */
3448 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3449 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3450 #endif /* LARGE_SMB_OFF_T */
3451 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3452 fname, (double)allocation_size ));
3454 if (allocation_size) {
3455 allocation_size = smb_roundup(conn, allocation_size);
3458 if(allocation_size != get_file_size(sbuf)) {
3459 SMB_STRUCT_STAT new_sbuf;
3461 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3462 fname, (double)allocation_size ));
3465 files_struct *new_fsp = NULL;
3466 int access_mode = 0;
3469 if(global_oplock_break) {
3470 /* Queue this file modify as we are the process of an oplock break. */
3472 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3473 DEBUGADD(2,( "in oplock break state.\n"));
3475 push_oplock_pending_smb_message(inbuf, length);
3479 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3480 SET_OPEN_MODE(DOS_OPEN_RDWR),
3481 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3482 FILE_ATTRIBUTE_NORMAL,
3483 INTERNAL_OPEN_ONLY, &access_mode, &action);
3485 if (new_fsp == NULL)
3486 return(UNIXERROR(ERRDOS,ERRbadpath));
3487 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3488 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3489 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3490 new_fsp->fnum, strerror(errno)));
3493 close_file(new_fsp,True);
3495 ret = vfs_allocate_file_space(fsp, allocation_size);
3496 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3497 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3498 fsp->fnum, strerror(errno)));
3503 return ERROR_NT(NT_STATUS_DISK_FULL);
3505 /* Allocate can truncate size... */
3506 size = get_file_size(new_sbuf);
3512 case SMB_FILE_END_OF_FILE_INFORMATION:
3513 case SMB_SET_FILE_END_OF_FILE_INFO:
3516 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3518 size = IVAL(pdata,0);
3519 #ifdef LARGE_SMB_OFF_T
3520 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3521 #else /* LARGE_SMB_OFF_T */
3522 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3523 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3524 #endif /* LARGE_SMB_OFF_T */
3525 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3529 case SMB_FILE_DISPOSITION_INFORMATION:
3530 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3532 BOOL delete_on_close;
3535 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3537 delete_on_close = (CVAL(pdata,0) ? True : False);
3539 /* Just ignore this set on a path. */
3540 if (tran_call != TRANSACT2_SETFILEINFO)
3544 return(UNIXERROR(ERRDOS,ERRbadfid));
3546 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3548 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3549 return ERROR_NT(status);
3551 /* The set is across all open files on this dev/inode pair. */
3552 status =set_delete_on_close_over_all(fsp, delete_on_close);
3553 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3554 return ERROR_NT(status);
3559 case SMB_FILE_POSITION_INFORMATION:
3561 SMB_BIG_UINT position_information;
3564 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3566 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3567 #ifdef LARGE_SMB_OFF_T
3568 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3569 #else /* LARGE_SMB_OFF_T */
3570 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3571 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3572 #endif /* LARGE_SMB_OFF_T */
3573 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3574 fname, (double)position_information ));
3576 fsp->position_information = position_information;
3581 * CIFS UNIX extensions.
3584 case SMB_SET_FILE_UNIX_BASIC:
3586 uint32 raw_unixmode;
3588 if (total_data < 100)
3589 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3591 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3592 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3593 size=IVAL(pdata,0); /* first 8 Bytes are size */
3594 #ifdef LARGE_SMB_OFF_T
3595 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3596 #else /* LARGE_SMB_OFF_T */
3597 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3598 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3599 #endif /* LARGE_SMB_OFF_T */
3601 pdata+=24; /* ctime & st_blocks are not changed */
3602 tvs.actime = interpret_long_date(pdata); /* access_time */
3603 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3605 set_owner = (uid_t)IVAL(pdata,0);
3607 set_grp = (gid_t)IVAL(pdata,0);
3609 raw_unixmode = IVAL(pdata,28);
3610 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3611 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3613 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3614 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3615 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3617 if (!VALID_STAT(sbuf)) {
3620 * The only valid use of this is to create character and block
3621 * devices, and named pipes. This is deprecated (IMHO) and
3622 * a new info level should be used for mknod. JRA.
3625 uint32 file_type = IVAL(pdata,0);
3626 #if defined(HAVE_MAKEDEV)
3627 uint32 dev_major = IVAL(pdata,4);
3628 uint32 dev_minor = IVAL(pdata,12);
3631 uid_t myuid = geteuid();
3632 gid_t mygid = getegid();
3633 SMB_DEV_T dev = (SMB_DEV_T)0;
3635 if (tran_call == TRANSACT2_SETFILEINFO)
3636 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3638 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3639 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3641 #if defined(HAVE_MAKEDEV)
3642 dev = makedev(dev_major, dev_minor);
3645 /* We can only create as the owner/group we are. */
3647 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3648 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3649 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3650 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3652 switch (file_type) {
3653 #if defined(S_IFIFO)
3654 case UNIX_TYPE_FIFO:
3655 unixmode |= S_IFIFO;
3658 #if defined(S_IFSOCK)
3659 case UNIX_TYPE_SOCKET:
3660 unixmode |= S_IFSOCK;
3663 #if defined(S_IFCHR)
3664 case UNIX_TYPE_CHARDEV:
3665 unixmode |= S_IFCHR;
3668 #if defined(S_IFBLK)
3669 case UNIX_TYPE_BLKDEV:
3670 unixmode |= S_IFBLK;
3674 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3677 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3678 0%o for file %s\n", (double)dev, unixmode, fname ));
3680 /* Ok - do the mknod. */
3681 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3682 return(UNIXERROR(ERRDOS,ERRnoaccess));
3684 inherit_access_acl(conn, fname, unixmode);
3687 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3692 * Deal with the UNIX specific mode set.
3695 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3696 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3697 (unsigned int)unixmode, fname ));
3698 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3699 return(UNIXERROR(ERRDOS,ERRnoaccess));
3703 * Deal with the UNIX specific uid set.
3706 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3707 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3708 (unsigned int)set_owner, fname ));
3709 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3710 return(UNIXERROR(ERRDOS,ERRnoaccess));
3714 * Deal with the UNIX specific gid set.
3717 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3718 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3719 (unsigned int)set_owner, fname ));
3720 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3721 return(UNIXERROR(ERRDOS,ERRnoaccess));
3726 case SMB_SET_FILE_UNIX_LINK:
3728 pstring link_target;
3729 char *newname = fname;
3731 /* Set a symbolic link. */
3732 /* Don't allow this if follow links is false. */
3734 if (!lp_symlinks(SNUM(conn)))
3735 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3737 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3739 /* !widelinks forces the target path to be within the share. */
3740 /* This means we can interpret the target as a pathname. */
3741 if (!lp_widelinks(SNUM(conn))) {
3743 char *last_dirp = NULL;
3745 unix_format(link_target);
3746 if (*link_target == '/') {
3747 /* No absolute paths allowed. */
3748 return(UNIXERROR(ERRDOS,ERRnoaccess));
3750 pstrcpy(rel_name, newname);
3751 last_dirp = strrchr_m(rel_name, '/');
3753 last_dirp[1] = '\0';
3755 pstrcpy(rel_name, "./");
3757 pstrcat(rel_name, link_target);
3759 if (!check_name(rel_name, conn)) {
3760 return(UNIXERROR(ERRDOS,ERRnoaccess));
3764 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3765 fname, link_target ));
3767 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3768 return(UNIXERROR(ERRDOS,ERRnoaccess));
3770 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3774 case SMB_SET_FILE_UNIX_HLINK:
3777 char *newname = fname;
3779 /* Set a hard link. */
3780 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3781 if (!NT_STATUS_IS_OK(status)) {
3782 return ERROR_NT(status);
3785 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3788 status = hardlink_internals(conn, oldname, newname);
3789 if (!NT_STATUS_IS_OK(status)) {
3790 return ERROR_NT(status);
3794 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3798 case SMB_FILE_RENAME_INFORMATION:
3807 if (total_data < 12)
3808 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3810 overwrite = (CVAL(pdata,0) ? True : False);
3811 root_fid = IVAL(pdata,4);
3812 len = IVAL(pdata,8);
3813 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3814 if (!NT_STATUS_IS_OK(status)) {
3815 return ERROR_NT(status);
3818 /* Check the new name has no '/' characters. */
3819 if (strchr_m(newname, '/'))
3820 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3822 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3824 /* Create the base directory. */
3825 pstrcpy(base_name, fname);
3826 p = strrchr_m(base_name, '/');
3829 /* Append the new name. */
3830 pstrcat(base_name, "/");
3831 pstrcat(base_name, newname);
3834 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3835 fsp->fnum, fsp->fsp_name, base_name ));
3836 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3838 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3840 status = rename_internals(conn, fname, base_name, 0, overwrite);
3842 if (!NT_STATUS_IS_OK(status)) {
3843 return ERROR_NT(status);
3845 process_pending_change_notify_queue((time_t)0);
3847 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3851 #if defined(HAVE_POSIX_ACLS)
3852 case SMB_SET_POSIX_ACL:
3854 uint16 posix_acl_version;
3855 uint16 num_file_acls;
3856 uint16 num_def_acls;
3857 BOOL valid_file_acls = True;
3858 BOOL valid_def_acls = True;
3860 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3861 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3863 posix_acl_version = SVAL(pdata,0);
3864 num_file_acls = SVAL(pdata,2);
3865 num_def_acls = SVAL(pdata,4);
3867 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3868 valid_file_acls = False;
3872 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3873 valid_def_acls = False;
3877 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3878 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3881 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3882 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3883 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3886 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3887 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3888 return(UNIXERROR(ERRDOS,ERRnoaccess));
3891 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3892 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3893 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3894 return(UNIXERROR(ERRDOS,ERRnoaccess));
3898 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3904 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3907 /* get some defaults (no modifications) if any info is zero or -1. */
3908 if (null_mtime(tvs.actime)) {
3909 tvs.actime = sbuf.st_atime;
3912 if (null_mtime(tvs.modtime)) {
3913 tvs.modtime = sbuf.st_mtime;
3916 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3917 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3918 DEBUG(6,("size: %.0f ", (double)size));
3921 if (S_ISDIR(sbuf.st_mode))
3927 DEBUG(6,("dosmode: %x\n" , dosmode));
3929 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3930 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3931 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3932 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3935 * Only do this test if we are not explicitly
3936 * changing the size of a file.
3939 size = get_file_size(sbuf);
3943 * Try and set the times, size and mode of this file -
3944 * if they are different from the current values
3947 /* check the mode isn't different, before changing it */
3948 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3950 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3952 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3953 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3954 return(UNIXERROR(ERRDOS,ERRnoaccess));
3959 if (size != get_file_size(sbuf)) {
3963 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3964 fname, (double)size ));
3967 files_struct *new_fsp = NULL;
3968 int access_mode = 0;
3971 if(global_oplock_break) {
3972 /* Queue this file modify as we are the process of an oplock break. */
3974 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3975 DEBUGADD(2,( "in oplock break state.\n"));
3977 push_oplock_pending_smb_message(inbuf, length);
3981 new_fsp = open_file_shared(conn, fname, &sbuf,
3982 SET_OPEN_MODE(DOS_OPEN_RDWR),
3983 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3984 FILE_ATTRIBUTE_NORMAL,
3985 INTERNAL_OPEN_ONLY, &access_mode, &action);
3987 if (new_fsp == NULL)
3988 return(UNIXERROR(ERRDOS,ERRbadpath));
3989 ret = vfs_set_filelen(new_fsp, size);
3990 close_file(new_fsp,True);
3992 ret = vfs_set_filelen(fsp, size);
3996 return (UNIXERROR(ERRHRD,ERRdiskfull));
4000 * Finally the times.
4002 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4005 * This was a setfileinfo on an open file.
4006 * NT does this a lot. We also need to
4007 * set the time here, as it can be read by
4008 * FindFirst/FindNext and with the patch for bug #2045
4009 * in smbd/fileio.c it ensures that this timestamp is
4010 * kept sticky even after a write. We save the request
4011 * away and will set it on file close and after a write. JRA.
4014 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4015 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4016 fsp_set_pending_modtime(fsp, tvs.modtime);
4020 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4022 if(file_utime(conn, fname, &tvs)!=0) {
4023 return(UNIXERROR(ERRDOS,ERRnoaccess));
4028 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4033 /****************************************************************************
4034 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4035 ****************************************************************************/
4037 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4038 char **pparams, int total_params, char **ppdata, int total_data,
4039 unsigned int max_data_bytes)
4041 char *params = *pparams;
4044 SMB_STRUCT_STAT sbuf;
4045 BOOL bad_path = False;
4046 NTSTATUS status = NT_STATUS_OK;
4048 if (!CAN_WRITE(conn))
4049 return ERROR_DOS(ERRSRV,ERRaccess);
4051 if (total_params < 4)
4052 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4054 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4055 if (!NT_STATUS_IS_OK(status)) {
4056 return ERROR_NT(status);
4059 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4061 unix_convert(directory,conn,0,&bad_path,&sbuf);
4063 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4065 if (check_name(directory,conn))
4066 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4069 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4070 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4073 /* Realloc the parameter and data sizes */
4074 params = SMB_REALLOC(*pparams,2);
4076 return ERROR_DOS(ERRDOS,ERRnomem);
4081 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4086 /****************************************************************************
4087 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4088 We don't actually do this - we just send a null response.
4089 ****************************************************************************/
4091 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4092 char **pparams, int total_params, char **ppdata, int total_data,
4093 unsigned int max_data_bytes)
4095 static uint16 fnf_handle = 257;
4096 char *params = *pparams;
4099 if (total_params < 6)
4100 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4102 info_level = SVAL(params,4);
4103 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4105 switch (info_level) {
4110 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4113 /* Realloc the parameter and data sizes */
4114 params = SMB_REALLOC(*pparams,6);
4116 return ERROR_DOS(ERRDOS,ERRnomem);
4119 SSVAL(params,0,fnf_handle);
4120 SSVAL(params,2,0); /* No changes */
4121 SSVAL(params,4,0); /* No EA errors */
4128 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4133 /****************************************************************************
4134 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4135 changes). Currently this does nothing.
4136 ****************************************************************************/
4138 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4139 char **pparams, int total_params, char **ppdata, int total_data,
4140 unsigned int max_data_bytes)
4142 char *params = *pparams;
4144 DEBUG(3,("call_trans2findnotifynext\n"));
4146 /* Realloc the parameter and data sizes */
4147 params = SMB_REALLOC(*pparams,4);
4149 return ERROR_DOS(ERRDOS,ERRnomem);
4152 SSVAL(params,0,0); /* No changes */
4153 SSVAL(params,2,0); /* No EA errors */
4155 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4160 /****************************************************************************
4161 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4162 ****************************************************************************/
4164 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4165 char **pparams, int total_params, char **ppdata, int total_data,
4166 unsigned int max_data_bytes)
4168 char *params = *pparams;
4171 int max_referral_level;
4173 DEBUG(10,("call_trans2getdfsreferral\n"));
4175 if (total_params < 2)
4176 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4178 max_referral_level = SVAL(params,0);
4180 if(!lp_host_msdfs())
4181 return ERROR_DOS(ERRDOS,ERRbadfunc);
4183 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4184 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4185 return UNIXERROR(ERRDOS,ERRbadfile);
4187 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4188 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4193 #define LMCAT_SPL 0x53
4194 #define LMFUNC_GETJOBID 0x60
4196 /****************************************************************************
4197 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4198 ****************************************************************************/
4200 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4201 char **pparams, int total_params, char **ppdata, int total_data,
4202 unsigned int max_data_bytes)
4204 char *pdata = *ppdata;
4205 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4207 /* check for an invalid fid before proceeding */
4210 return(ERROR_DOS(ERRDOS,ERRbadfid));
4212 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4213 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4214 pdata = SMB_REALLOC(*ppdata, 32);
4216 return ERROR_DOS(ERRDOS,ERRnomem);
4219 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4220 CAN ACCEPT THIS IN UNICODE. JRA. */
4222 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4223 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4224 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4225 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4228 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4229 return ERROR_DOS(ERRSRV,ERRerror);
4233 /****************************************************************************
4234 Reply to a SMBfindclose (stop trans2 directory search).
4235 ****************************************************************************/
4237 int reply_findclose(connection_struct *conn,
4238 char *inbuf,char *outbuf,int length,int bufsize)
4241 int dptr_num=SVALS(inbuf,smb_vwv0);
4242 START_PROFILE(SMBfindclose);
4244 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4246 dptr_close(&dptr_num);
4248 outsize = set_message(outbuf,0,0,True);
4250 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4252 END_PROFILE(SMBfindclose);
4256 /****************************************************************************
4257 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4258 ****************************************************************************/
4260 int reply_findnclose(connection_struct *conn,
4261 char *inbuf,char *outbuf,int length,int bufsize)
4265 START_PROFILE(SMBfindnclose);
4267 dptr_num = SVAL(inbuf,smb_vwv0);
4269 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4271 /* We never give out valid handles for a
4272 findnotifyfirst - so any dptr_num is ok here.
4275 outsize = set_message(outbuf,0,0,True);
4277 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4279 END_PROFILE(SMBfindnclose);
4283 /****************************************************************************
4284 Reply to a SMBtranss2 - just ignore it!
4285 ****************************************************************************/
4287 int reply_transs2(connection_struct *conn,
4288 char *inbuf,char *outbuf,int length,int bufsize)
4290 START_PROFILE(SMBtranss2);
4291 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4292 END_PROFILE(SMBtranss2);
4296 /****************************************************************************
4297 Reply to a SMBtrans2.
4298 ****************************************************************************/
4300 int reply_trans2(connection_struct *conn,
4301 char *inbuf,char *outbuf,int length,int bufsize)
4304 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4305 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4306 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4308 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4309 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4310 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4311 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4312 int32 timeout = IVALS(inbuf,smb_timeout);
4314 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4315 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4316 char *params = NULL, *data = NULL;
4317 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4318 START_PROFILE(SMBtrans2);
4320 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4321 /* Queue this open message as we are the process of an
4324 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4325 DEBUGADD(2,( "in oplock break state.\n"));
4327 push_oplock_pending_smb_message(inbuf, length);
4328 END_PROFILE(SMBtrans2);
4332 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4333 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4334 END_PROFILE(SMBtrans2);
4335 return ERROR_DOS(ERRSRV,ERRaccess);
4338 outsize = set_message(outbuf,0,0,True);
4340 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4341 is so as a sanity check */
4344 * Need to have rc=0 for ioctl to get job id for OS/2.
4345 * Network printing will fail if function is not successful.
4346 * Similar function in reply.c will be used if protocol
4347 * is LANMAN1.0 instead of LM1.2X002.
4348 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4349 * outbuf doesn't have to be set(only job id is used).
4351 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4352 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4353 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4354 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4356 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4357 DEBUG(2,("Transaction is %d\n",tran_call));
4358 END_PROFILE(SMBtrans2);
4359 ERROR_DOS(ERRDOS,ERRinvalidparam);
4363 /* Allocate the space for the maximum needed parameters and data */
4364 if (total_params > 0)
4365 params = (char *)SMB_MALLOC(total_params);
4367 data = (char *)SMB_MALLOC(total_data);
4369 if ((total_params && !params) || (total_data && !data)) {
4370 DEBUG(2,("Out of memory in reply_trans2\n"));
4373 END_PROFILE(SMBtrans2);
4374 return ERROR_DOS(ERRDOS,ERRnomem);
4377 /* Copy the param and data bytes sent with this request into
4378 the params buffer */
4379 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4380 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4382 if (num_params > total_params || num_data > total_data)
4383 exit_server("invalid params in reply_trans2");
4386 unsigned int psoff = SVAL(inbuf, smb_psoff);
4387 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4389 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4390 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4392 memcpy( params, smb_base(inbuf) + psoff, num_params);
4395 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4396 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4398 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4399 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4401 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4404 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4406 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4407 /* We need to send an interim response then receive the rest
4408 of the parameter/data bytes */
4409 outsize = set_message(outbuf,0,0,True);
4410 srv_signing_trans_stop();
4411 if (!send_smb(smbd_server_fd(),outbuf))
4412 exit_server("reply_trans2: send_smb failed.");
4414 while (num_data_sofar < total_data ||
4415 num_params_sofar < total_params) {
4417 unsigned int param_disp;
4418 unsigned int param_off;
4419 unsigned int data_disp;
4420 unsigned int data_off;
4422 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4425 * The sequence number for the trans reply is always
4426 * based on the last secondary received.
4429 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4432 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4433 outsize = set_message(outbuf,0,0,True);
4435 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4437 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4438 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4442 /* Revise total_params and total_data in case
4443 they have changed downwards */
4444 if (SVAL(inbuf, smb_tpscnt) < total_params)
4445 total_params = SVAL(inbuf, smb_tpscnt);
4446 if (SVAL(inbuf, smb_tdscnt) < total_data)
4447 total_data = SVAL(inbuf, smb_tdscnt);
4449 num_params = SVAL(inbuf,smb_spscnt);
4450 param_off = SVAL(inbuf, smb_spsoff);
4451 param_disp = SVAL(inbuf, smb_spsdisp);
4452 num_params_sofar += num_params;
4454 num_data = SVAL(inbuf, smb_sdscnt);
4455 data_off = SVAL(inbuf, smb_sdsoff);
4456 data_disp = SVAL(inbuf, smb_sdsdisp);
4457 num_data_sofar += num_data;
4459 if (num_params_sofar > total_params || num_data_sofar > total_data)
4463 if (param_disp + num_params > total_params)
4465 if ((param_disp + num_params < param_disp) ||
4466 (param_disp + num_params < num_params))
4468 if (param_disp > total_params)
4470 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4471 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4473 if (params + param_disp < params)
4476 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4479 if (data_disp + num_data > total_data)
4481 if ((data_disp + num_data < data_disp) ||
4482 (data_disp + num_data < num_data))
4484 if (data_disp > total_data)
4486 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4487 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4489 if (data + data_disp < data)
4492 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4497 if (Protocol >= PROTOCOL_NT1) {
4498 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4501 /* Now we must call the relevant TRANS2 function */
4503 case TRANSACT2_OPEN:
4504 START_PROFILE_NESTED(Trans2_open);
4505 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4506 ¶ms, total_params, &data, total_data, max_data_bytes);
4507 END_PROFILE_NESTED(Trans2_open);
4510 case TRANSACT2_FINDFIRST:
4511 START_PROFILE_NESTED(Trans2_findfirst);
4512 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4513 ¶ms, total_params, &data, total_data, max_data_bytes);
4514 END_PROFILE_NESTED(Trans2_findfirst);
4517 case TRANSACT2_FINDNEXT:
4518 START_PROFILE_NESTED(Trans2_findnext);
4519 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4520 ¶ms, total_params, &data, total_data, max_data_bytes);
4521 END_PROFILE_NESTED(Trans2_findnext);
4524 case TRANSACT2_QFSINFO:
4525 START_PROFILE_NESTED(Trans2_qfsinfo);
4526 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4527 ¶ms, total_params, &data, total_data, max_data_bytes);
4528 END_PROFILE_NESTED(Trans2_qfsinfo);
4531 #ifdef HAVE_SYS_QUOTAS
4532 case TRANSACT2_SETFSINFO:
4533 START_PROFILE_NESTED(Trans2_setfsinfo);
4534 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4535 ¶ms, total_params, &data, total_data, max_data_bytes);
4536 END_PROFILE_NESTED(Trans2_setfsinfo);
4539 case TRANSACT2_QPATHINFO:
4540 case TRANSACT2_QFILEINFO:
4541 START_PROFILE_NESTED(Trans2_qpathinfo);
4542 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4543 ¶ms, total_params, &data, total_data, max_data_bytes);
4544 END_PROFILE_NESTED(Trans2_qpathinfo);
4546 case TRANSACT2_SETPATHINFO:
4547 case TRANSACT2_SETFILEINFO:
4548 START_PROFILE_NESTED(Trans2_setpathinfo);
4549 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4550 ¶ms, total_params, &data, total_data, max_data_bytes);
4551 END_PROFILE_NESTED(Trans2_setpathinfo);
4554 case TRANSACT2_FINDNOTIFYFIRST:
4555 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4556 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4557 ¶ms, total_params, &data, total_data, max_data_bytes);
4558 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4561 case TRANSACT2_FINDNOTIFYNEXT:
4562 START_PROFILE_NESTED(Trans2_findnotifynext);
4563 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4564 ¶ms, total_params, &data, total_data, max_data_bytes);
4565 END_PROFILE_NESTED(Trans2_findnotifynext);
4567 case TRANSACT2_MKDIR:
4568 START_PROFILE_NESTED(Trans2_mkdir);
4569 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4570 ¶ms, total_params, &data, total_data, max_data_bytes);
4571 END_PROFILE_NESTED(Trans2_mkdir);
4574 case TRANSACT2_GET_DFS_REFERRAL:
4575 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4576 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4577 ¶ms, total_params, &data, total_data, max_data_bytes);
4578 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4580 case TRANSACT2_IOCTL:
4581 START_PROFILE_NESTED(Trans2_ioctl);
4582 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4583 ¶ms, total_params, &data, total_data, max_data_bytes);
4584 END_PROFILE_NESTED(Trans2_ioctl);
4587 /* Error in request */
4588 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4591 END_PROFILE(SMBtrans2);
4592 srv_signing_trans_stop();
4593 return ERROR_DOS(ERRSRV,ERRerror);
4596 /* As we do not know how many data packets will need to be
4597 returned here the various call_trans2xxxx calls
4598 must send their own. Thus a call_trans2xxx routine only
4599 returns a value other than -1 when it wants to send
4603 srv_signing_trans_stop();
4607 END_PROFILE(SMBtrans2);
4608 return outsize; /* If a correct response was needed the
4609 call_trans2xxx calls have already sent
4610 it. If outsize != -1 then it is returning */
4614 srv_signing_trans_stop();
4617 END_PROFILE(SMBtrans2);
4618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);