2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
63 if(S_ISDIR(sbuf->st_mode)) {
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
165 struct ea_list *ea_list_head = NULL;
169 if (!lp_ea_support(SNUM(conn))) {
173 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
180 if (fsp && fsp->fh->fd != -1) {
181 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
183 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
186 if (sizeret == -1 && errno == ERANGE) {
187 ea_namelist_size *= 2;
196 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
199 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200 struct ea_list *listp;
202 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
205 listp = TALLOC_P(mem_ctx, struct ea_list);
209 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
215 push_ascii_fstring(dos_ea_name, listp->ea.name);
216 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218 (unsigned int)*pea_total_len, dos_ea_name,
219 (unsigned int)listp->ea.value.length ));
221 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
223 /* Add on 4 for total length. */
224 if (*pea_total_len) {
229 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
233 /****************************************************************************
234 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
236 ****************************************************************************/
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239 connection_struct *conn, struct ea_list *ea_list)
241 unsigned int ret_data_size = 4;
244 SMB_ASSERT(total_data_size >= 4);
246 if (!lp_ea_support(SNUM(conn))) {
251 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
254 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255 dos_namelen = strlen(dos_ea_name);
256 if (dos_namelen > 255 || dos_namelen == 0) {
259 if (ea_list->ea.value.length > 65535) {
262 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
266 /* We know we have room. */
267 SCVAL(p,0,ea_list->ea.flags);
268 SCVAL(p,1,dos_namelen);
269 SSVAL(p,2,ea_list->ea.value.length);
270 fstrcpy(p+4, dos_ea_name);
271 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
273 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
277 ret_data_size = PTR_DIFF(p, pdata);
278 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279 SIVAL(pdata,0,ret_data_size);
280 return ret_data_size;
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
285 size_t total_ea_len = 0;
286 TALLOC_CTX *mem_ctx = NULL;
288 if (!lp_ea_support(SNUM(conn))) {
291 mem_ctx = talloc_init("estimate_ea_size");
292 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293 talloc_destroy(mem_ctx);
297 /****************************************************************************
298 Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
304 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
307 for (; ea_list; ea_list = ea_list->next) {
308 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310 &unix_ea_name[5], ea_list->ea.name));
311 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
315 talloc_destroy(mem_ctx);
318 /****************************************************************************
319 Set or delete an extended attribute.
320 ****************************************************************************/
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
324 if (!lp_ea_support(SNUM(conn))) {
325 return NT_STATUS_EAS_NOT_SUPPORTED;
328 for (;ea_list; ea_list = ea_list->next) {
330 fstring unix_ea_name;
332 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333 fstrcat(unix_ea_name, ea_list->ea.name);
335 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
337 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
339 if (samba_private_attr_name(unix_ea_name)) {
340 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341 return NT_STATUS_ACCESS_DENIED;
344 if (ea_list->ea.value.length == 0) {
345 /* Remove the attribute. */
346 if (fsp && (fsp->fh->fd != -1)) {
347 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348 unix_ea_name, fsp->fsp_name));
349 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
351 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352 unix_ea_name, fname));
353 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
356 /* Removing a non existent attribute always succeeds. */
357 if (ret == -1 && errno == ENOATTR) {
358 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
364 if (fsp && (fsp->fh->fd != -1)) {
365 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366 unix_ea_name, fsp->fsp_name));
367 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
370 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371 unix_ea_name, fname));
372 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 if (errno == ENOTSUP) {
380 return NT_STATUS_EAS_NOT_SUPPORTED;
383 return map_nt_error_from_unix(errno);
389 /****************************************************************************
390 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
395 struct ea_list *ea_list_head = NULL;
398 while (offset + 2 < data_size) {
399 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
400 unsigned int namelen = CVAL(pdata,offset);
402 offset++; /* Go past the namelen byte. */
404 /* integer wrap paranioa. */
405 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
406 (offset > data_size) || (namelen > data_size) ||
407 (offset + namelen >= data_size)) {
410 /* Ensure the name is null terminated. */
411 if (pdata[offset + namelen] != '\0') {
414 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
419 offset += (namelen + 1); /* Go past the name + terminating zero. */
420 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
421 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
427 /****************************************************************************
428 Read one EA list entry from the buffer.
429 ****************************************************************************/
431 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
433 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
435 unsigned int namelen;
445 eal->ea.flags = CVAL(pdata,0);
446 namelen = CVAL(pdata,1);
447 val_len = SVAL(pdata,2);
449 if (4 + namelen + 1 + val_len > data_size) {
453 /* Ensure the name is null terminated. */
454 if (pdata[namelen + 4] != '\0') {
457 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
462 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
463 if (!eal->ea.value.data) {
467 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
469 /* Ensure we're null terminated just in case we print the value. */
470 eal->ea.value.data[val_len] = '\0';
471 /* But don't count the null. */
472 eal->ea.value.length--;
475 *pbytes_used = 4 + namelen + 1 + val_len;
478 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
479 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
484 /****************************************************************************
485 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
488 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 struct ea_list *ea_list_head = NULL;
492 size_t bytes_used = 0;
494 while (offset < data_size) {
495 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
501 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
502 offset += bytes_used;
508 /****************************************************************************
509 Count the total EA size needed.
510 ****************************************************************************/
512 static size_t ea_list_size(struct ea_list *ealist)
515 struct ea_list *listp;
518 for (listp = ealist; listp; listp = listp->next) {
519 push_ascii_fstring(dos_ea_name, listp->ea.name);
520 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
522 /* Add on 4 for total length. */
530 /****************************************************************************
531 Return a union of EA's from a file list and a list of names.
532 The TALLOC context for the two lists *MUST* be identical as we steal
533 memory from one list to add to another. JRA.
534 ****************************************************************************/
536 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
538 struct ea_list *nlistp, *flistp;
540 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
541 for (flistp = file_list; flistp; flistp = flistp->next) {
542 if (strequal(nlistp->ea.name, flistp->ea.name)) {
548 /* Copy the data from this entry. */
549 nlistp->ea.flags = flistp->ea.flags;
550 nlistp->ea.value = flistp->ea.value;
553 nlistp->ea.flags = 0;
554 ZERO_STRUCT(nlistp->ea.value);
558 *total_ea_len = ea_list_size(name_list);
562 /****************************************************************************
563 Send the required number of replies back.
564 We assume all fields other than the data fields are
565 set correctly for the type of call.
566 HACK ! Always assumes smb_setup field is zero.
567 ****************************************************************************/
569 int send_trans2_replies(char *outbuf,
577 /* As we are using a protocol > LANMAN1 then the max_send
578 variable must have been set in the sessetupX call.
579 This takes precedence over the max_xmit field in the
580 global struct. These different max_xmit variables should
581 be merged as this is now too confusing */
583 int data_to_send = datasize;
584 int params_to_send = paramsize;
586 const char *pp = params;
587 const char *pd = pdata;
588 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
589 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
590 int data_alignment_offset = 0;
592 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
594 set_message(outbuf,10,0,True);
596 /* Modify the data_to_send and datasize and set the error if
597 we're trying to send more than max_data_bytes. We still send
598 the part of the packet(s) that fit. Strange, but needed
601 if (max_data_bytes > 0 && datasize > max_data_bytes) {
602 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
603 max_data_bytes, datasize ));
604 datasize = data_to_send = max_data_bytes;
605 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
608 /* If there genuinely are no parameters or data to send just send the empty packet */
610 if(params_to_send == 0 && data_to_send == 0) {
612 if (!send_smb(smbd_server_fd(),outbuf))
613 exit_server_cleanly("send_trans2_replies: send_smb failed.");
617 /* When sending params and data ensure that both are nicely aligned */
618 /* Only do this alignment when there is also data to send - else
619 can cause NT redirector problems. */
621 if (((params_to_send % 4) != 0) && (data_to_send != 0))
622 data_alignment_offset = 4 - (params_to_send % 4);
624 /* Space is bufsize minus Netbios over TCP header minus SMB header */
625 /* The alignment_offset is to align the param bytes on an even byte
626 boundary. NT 4.0 Beta needs this to work correctly. */
628 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
630 /* useable_space can never be more than max_send minus the alignment offset. */
632 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
634 while (params_to_send || data_to_send) {
635 /* Calculate whether we will totally or partially fill this packet */
637 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
639 /* We can never send more than useable_space */
641 * Note that 'useable_space' does not include the alignment offsets,
642 * but we must include the alignment offsets in the calculation of
643 * the length of the data we send over the wire, as the alignment offsets
644 * are sent here. Fix from Marc_Jacobsen@hp.com.
647 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
649 set_message(outbuf, 10, total_sent_thistime, True);
651 /* Set total params and data to be sent */
652 SSVAL(outbuf,smb_tprcnt,paramsize);
653 SSVAL(outbuf,smb_tdrcnt,datasize);
655 /* Calculate how many parameters and data we can fit into
656 * this packet. Parameters get precedence
659 params_sent_thistime = MIN(params_to_send,useable_space);
660 data_sent_thistime = useable_space - params_sent_thistime;
661 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
663 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
665 /* smb_proff is the offset from the start of the SMB header to the
666 parameter bytes, however the first 4 bytes of outbuf are
667 the Netbios over TCP header. Thus use smb_base() to subtract
668 them from the calculation */
670 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
672 if(params_sent_thistime == 0)
673 SSVAL(outbuf,smb_prdisp,0);
675 /* Absolute displacement of param bytes sent in this packet */
676 SSVAL(outbuf,smb_prdisp,pp - params);
678 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
679 if(data_sent_thistime == 0) {
680 SSVAL(outbuf,smb_droff,0);
681 SSVAL(outbuf,smb_drdisp, 0);
683 /* The offset of the data bytes is the offset of the
684 parameter bytes plus the number of parameters being sent this time */
685 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
686 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
687 SSVAL(outbuf,smb_drdisp, pd - pdata);
690 /* Copy the param bytes into the packet */
692 if(params_sent_thistime)
693 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
695 /* Copy in the data bytes */
696 if(data_sent_thistime)
697 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
698 data_alignment_offset,pd,data_sent_thistime);
700 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
701 params_sent_thistime, data_sent_thistime, useable_space));
702 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
703 params_to_send, data_to_send, paramsize, datasize));
705 /* Send the packet */
707 if (!send_smb(smbd_server_fd(),outbuf))
708 exit_server_cleanly("send_trans2_replies: send_smb failed.");
710 pp += params_sent_thistime;
711 pd += data_sent_thistime;
713 params_to_send -= params_sent_thistime;
714 data_to_send -= data_sent_thistime;
717 if(params_to_send < 0 || data_to_send < 0) {
718 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
719 params_to_send, data_to_send));
727 /****************************************************************************
728 Reply to a TRANSACT2_OPEN.
729 ****************************************************************************/
731 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
732 char **pparams, int total_params, char **ppdata, int total_data,
733 unsigned int max_data_bytes)
735 char *params = *pparams;
736 char *pdata = *ppdata;
741 BOOL return_additional_info;
752 SMB_STRUCT_STAT sbuf;
755 struct ea_list *ea_list = NULL;
760 uint32 create_disposition;
761 uint32 create_options = 0;
764 * Ensure we have enough parameters to perform the operation.
767 if (total_params < 29) {
768 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
771 flags = SVAL(params, 0);
772 deny_mode = SVAL(params, 2);
773 open_attr = SVAL(params,6);
774 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
775 if (oplock_request) {
776 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
780 return_additional_info = BITSETW(params,0);
781 open_sattr = SVAL(params, 4);
782 open_time = make_unix_date3(params+8);
784 open_ofun = SVAL(params,12);
785 open_size = IVAL(params,14);
789 return(ERROR_DOS(ERRSRV,ERRaccess));
792 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
793 if (!NT_STATUS_IS_OK(status)) {
794 return ERROR_NT(status);
797 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
798 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
799 (unsigned int)open_ofun, open_size));
801 /* XXXX we need to handle passed times, sattr and flags */
803 status = unix_convert(conn, fname, False, NULL, &sbuf);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 status = check_name(conn, fname);
809 if (!NT_STATUS_IS_OK(status)) {
810 return ERROR_NT(status);
813 if (open_ofun == 0) {
814 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
817 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
822 return ERROR_DOS(ERRDOS, ERRbadaccess);
825 /* Any data in this call is an EA list. */
826 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
827 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
830 if (total_data != 4) {
831 if (total_data < 10) {
832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
835 if (IVAL(pdata,0) > total_data) {
836 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
837 IVAL(pdata,0), (unsigned int)total_data));
838 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
841 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 } else if (IVAL(pdata,0) != 4) {
847 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
850 status = open_file_ntcreate(conn,fname,&sbuf,
859 if (!NT_STATUS_IS_OK(status)) {
860 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
861 /* We have re-scheduled this call. */
864 return ERROR_NT(status);
867 size = get_file_size(sbuf);
868 fattr = dos_mode(conn,fname,&sbuf);
869 mtime = sbuf.st_mtime;
872 close_file(fsp,ERROR_CLOSE);
873 return(ERROR_DOS(ERRDOS,ERRnoaccess));
876 /* Save the requested allocation size. */
877 /* Allocate space for the file if a size hint is supplied */
878 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
879 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
880 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
881 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
882 if (fsp->is_directory) {
883 close_file(fsp,ERROR_CLOSE);
884 /* Can't set allocation size on a directory. */
885 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
887 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
888 close_file(fsp,ERROR_CLOSE);
889 return ERROR_NT(NT_STATUS_DISK_FULL);
892 /* Adjust size here to return the right size in the reply.
893 Windows does it this way. */
894 size = fsp->initial_allocation_size;
896 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
900 if (ea_list && smb_action == FILE_WAS_CREATED) {
901 status = set_ea(conn, fsp, fname, ea_list);
902 if (!NT_STATUS_IS_OK(status)) {
903 close_file(fsp,ERROR_CLOSE);
904 return ERROR_NT(status);
908 /* Realloc the size of parameters and data we will return */
909 *pparams = (char *)SMB_REALLOC(*pparams, 30);
910 if(*pparams == NULL ) {
911 return ERROR_NT(NT_STATUS_NO_MEMORY);
915 SSVAL(params,0,fsp->fnum);
916 SSVAL(params,2,fattr);
917 srv_put_dos_date2(params,4, mtime);
918 SIVAL(params,8, (uint32)size);
919 SSVAL(params,12,deny_mode);
920 SSVAL(params,14,0); /* open_type - file or directory. */
921 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
923 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
924 smb_action |= EXTENDED_OPLOCK_GRANTED;
927 SSVAL(params,18,smb_action);
930 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
932 SIVAL(params,20,inode);
933 SSVAL(params,24,0); /* Padding. */
935 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
936 SIVAL(params, 26, ea_size);
938 SIVAL(params, 26, 0);
941 /* Send the required number of replies */
942 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
947 /*********************************************************
948 Routine to check if a given string matches exactly.
949 as a special case a mask of "." does NOT match. That
950 is required for correct wildcard semantics
951 Case can be significant or not.
952 **********************************************************/
954 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
956 if (mask[0] == '.' && mask[1] == 0)
958 if (conn->case_sensitive)
959 return strcmp(str,mask)==0;
960 if (StrCaseCmp(str,mask) != 0) {
963 if (dptr_has_wild(conn->dirptr)) {
969 /****************************************************************************
970 Return the filetype for UNIX extensions.
971 ****************************************************************************/
973 static uint32 unix_filetype(mode_t mode)
976 return UNIX_TYPE_FILE;
977 else if(S_ISDIR(mode))
978 return UNIX_TYPE_DIR;
980 else if(S_ISLNK(mode))
981 return UNIX_TYPE_SYMLINK;
984 else if(S_ISCHR(mode))
985 return UNIX_TYPE_CHARDEV;
988 else if(S_ISBLK(mode))
989 return UNIX_TYPE_BLKDEV;
992 else if(S_ISFIFO(mode))
993 return UNIX_TYPE_FIFO;
996 else if(S_ISSOCK(mode))
997 return UNIX_TYPE_SOCKET;
1000 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1001 return UNIX_TYPE_UNKNOWN;
1004 /****************************************************************************
1005 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1006 ****************************************************************************/
1008 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1010 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1011 SMB_STRUCT_STAT *psbuf,
1013 enum perm_type ptype,
1018 if (perms == SMB_MODE_NO_CHANGE) {
1019 if (!VALID_STAT(*psbuf)) {
1020 return NT_STATUS_INVALID_PARAMETER;
1022 *ret_perms = psbuf->st_mode;
1023 return NT_STATUS_OK;
1027 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1028 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1029 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1030 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1031 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1032 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1033 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1034 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1035 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1037 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1040 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1043 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1048 /* Apply mode mask */
1049 ret &= lp_create_mask(SNUM(conn));
1050 /* Add in force bits */
1051 ret |= lp_force_create_mode(SNUM(conn));
1054 ret &= lp_dir_mask(SNUM(conn));
1055 /* Add in force bits */
1056 ret |= lp_force_dir_mode(SNUM(conn));
1058 case PERM_EXISTING_FILE:
1059 /* Apply mode mask */
1060 ret &= lp_security_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_security_mode(SNUM(conn));
1064 case PERM_EXISTING_DIR:
1065 /* Apply mode mask */
1066 ret &= lp_dir_security_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_dir_security_mode(SNUM(conn));
1073 return NT_STATUS_OK;
1076 /****************************************************************************
1077 Get a level dependent lanman2 dir entry.
1078 ****************************************************************************/
1080 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1081 void *inbuf, char *outbuf,
1082 char *path_mask,uint32 dirtype,int info_level,
1083 int requires_resume_key,
1084 BOOL dont_descend,char **ppdata,
1085 char *base_data, int space_remaining,
1086 BOOL *out_of_space, BOOL *got_exact_match,
1087 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1091 SMB_STRUCT_STAT sbuf;
1095 char *p, *q, *pdata = *ppdata;
1099 SMB_OFF_T file_size = 0;
1100 SMB_BIG_UINT allocation_size = 0;
1102 struct timespec mdate_ts, adate_ts, create_date_ts;
1103 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1105 char *last_entry_ptr;
1107 uint32 nt_extmode; /* Used for NT connections instead of mode */
1108 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1109 BOOL check_mangled_names = lp_manglednames(conn->params);
1112 *out_of_space = False;
1113 *got_exact_match = False;
1115 ZERO_STRUCT(mdate_ts);
1116 ZERO_STRUCT(adate_ts);
1117 ZERO_STRUCT(create_date_ts);
1122 p = strrchr_m(path_mask,'/');
1125 pstrcpy(mask,"*.*");
1129 pstrcpy(mask, path_mask);
1134 BOOL ms_dfs_link = False;
1136 /* Needed if we run out of space */
1137 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1138 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1141 * Due to bugs in NT client redirectors we are not using
1142 * resume keys any more - set them to zero.
1143 * Check out the related comments in findfirst/findnext.
1149 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1150 (long)conn->dirptr,curr_dirpos));
1155 pstrcpy(fname,dname);
1157 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1158 got_match = mask_match(fname, mask, conn->case_sensitive);
1160 if(!got_match && check_mangled_names &&
1161 !mangle_is_8_3(fname, False, conn->params)) {
1164 * It turns out that NT matches wildcards against
1165 * both long *and* short names. This may explain some
1166 * of the wildcard wierdness from old DOS clients
1167 * that some people have been seeing.... JRA.
1171 pstrcpy( newname, fname);
1172 mangle_map( newname, True, False, conn->params);
1173 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1174 got_match = mask_match(newname, mask, conn->case_sensitive);
1178 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1179 if (dont_descend && !isdots)
1182 pstrcpy(pathreal,conn->dirpath);
1184 pstrcat(pathreal,"/");
1185 pstrcat(pathreal,dname);
1187 if (INFO_LEVEL_IS_UNIX(info_level)) {
1188 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1189 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1190 pathreal,strerror(errno)));
1193 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1195 /* Needed to show the msdfs symlinks as
1198 if(lp_host_msdfs() &&
1199 lp_msdfs_root(SNUM(conn)) &&
1200 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1202 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1203 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1207 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1208 pathreal,strerror(errno)));
1214 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1216 mode = dos_mode(conn,pathreal,&sbuf);
1219 if (!dir_check_ftype(conn,mode,dirtype)) {
1220 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1225 file_size = get_file_size(sbuf);
1226 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1228 mdate_ts = get_mtimespec(&sbuf);
1229 adate_ts = get_atimespec(&sbuf);
1230 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1232 if (lp_dos_filetime_resolution(SNUM(conn))) {
1233 dos_filetime_timespec(&create_date_ts);
1234 dos_filetime_timespec(&mdate_ts);
1235 dos_filetime_timespec(&adate_ts);
1238 create_date = convert_timespec_to_time_t(create_date_ts);
1239 mdate = convert_timespec_to_time_t(mdate_ts);
1240 adate = convert_timespec_to_time_t(adate_ts);
1242 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1246 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1250 mangle_map(fname,False,True,conn->params);
1255 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1257 switch (info_level) {
1258 case SMB_FIND_INFO_STANDARD:
1259 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1260 if(requires_resume_key) {
1264 srv_put_dos_date2(p,0,create_date);
1265 srv_put_dos_date2(p,4,adate);
1266 srv_put_dos_date2(p,8,mdate);
1267 SIVAL(p,12,(uint32)file_size);
1268 SIVAL(p,16,(uint32)allocation_size);
1272 p += align_string(outbuf, p, 0);
1273 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1274 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1276 SCVAL(nameptr, -1, len - 2);
1278 SCVAL(nameptr, -1, 0);
1282 SCVAL(nameptr, -1, len - 1);
1284 SCVAL(nameptr, -1, 0);
1290 case SMB_FIND_EA_SIZE:
1291 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1292 if(requires_resume_key) {
1296 srv_put_dos_date2(p,0,create_date);
1297 srv_put_dos_date2(p,4,adate);
1298 srv_put_dos_date2(p,8,mdate);
1299 SIVAL(p,12,(uint32)file_size);
1300 SIVAL(p,16,(uint32)allocation_size);
1303 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1304 SIVAL(p,22,ea_size); /* Extended attributes */
1308 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1309 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1322 SCVAL(nameptr,0,len);
1324 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1327 case SMB_FIND_EA_LIST:
1329 struct ea_list *file_list = NULL;
1332 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1336 if(requires_resume_key) {
1340 srv_put_dos_date2(p,0,create_date);
1341 srv_put_dos_date2(p,4,adate);
1342 srv_put_dos_date2(p,8,mdate);
1343 SIVAL(p,12,(uint32)file_size);
1344 SIVAL(p,16,(uint32)allocation_size);
1346 p += 22; /* p now points to the EA area. */
1348 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1349 name_list = ea_list_union(name_list, file_list, &ea_len);
1351 /* We need to determine if this entry will fit in the space available. */
1352 /* Max string size is 255 bytes. */
1353 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1354 /* Move the dirptr back to prev_dirpos */
1355 dptr_SeekDir(conn->dirptr, prev_dirpos);
1356 *out_of_space = True;
1357 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1358 return False; /* Not finished - just out of space */
1361 /* Push the ea_data followed by the name. */
1362 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1364 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1365 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1378 SCVAL(nameptr,0,len);
1380 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1384 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1385 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1386 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1388 SIVAL(p,0,reskey); p += 4;
1389 put_long_date_timespec(p,create_date_ts); p += 8;
1390 put_long_date_timespec(p,adate_ts); p += 8;
1391 put_long_date_timespec(p,mdate_ts); p += 8;
1392 put_long_date_timespec(p,mdate_ts); p += 8;
1393 SOFF_T(p,0,file_size); p += 8;
1394 SOFF_T(p,0,allocation_size); p += 8;
1395 SIVAL(p,0,nt_extmode); p += 4;
1396 q = p; p += 4; /* q is placeholder for name length. */
1398 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1399 SIVAL(p,0,ea_size); /* Extended attributes */
1402 /* Clear the short name buffer. This is
1403 * IMPORTANT as not doing so will trigger
1404 * a Win2k client bug. JRA.
1406 if (!was_8_3 && check_mangled_names) {
1407 pstring mangled_name;
1408 pstrcpy(mangled_name, fname);
1409 mangle_map(mangled_name,True,True,
1411 mangled_name[12] = 0;
1412 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1414 memset(p + 2 + len,'\0',24 - len);
1421 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1424 SIVAL(p,0,0); /* Ensure any padding is null. */
1425 len = PTR_DIFF(p, pdata);
1426 len = (len + 3) & ~3;
1431 case SMB_FIND_FILE_DIRECTORY_INFO:
1432 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1434 SIVAL(p,0,reskey); p += 4;
1435 put_long_date_timespec(p,create_date_ts); p += 8;
1436 put_long_date_timespec(p,adate_ts); p += 8;
1437 put_long_date_timespec(p,mdate_ts); p += 8;
1438 put_long_date_timespec(p,mdate_ts); p += 8;
1439 SOFF_T(p,0,file_size); p += 8;
1440 SOFF_T(p,0,allocation_size); p += 8;
1441 SIVAL(p,0,nt_extmode); p += 4;
1442 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1445 SIVAL(p,0,0); /* Ensure any padding is null. */
1446 len = PTR_DIFF(p, pdata);
1447 len = (len + 3) & ~3;
1452 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1453 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1455 SIVAL(p,0,reskey); p += 4;
1456 put_long_date_timespec(p,create_date_ts); p += 8;
1457 put_long_date_timespec(p,adate_ts); p += 8;
1458 put_long_date_timespec(p,mdate_ts); p += 8;
1459 put_long_date_timespec(p,mdate_ts); p += 8;
1460 SOFF_T(p,0,file_size); p += 8;
1461 SOFF_T(p,0,allocation_size); p += 8;
1462 SIVAL(p,0,nt_extmode); p += 4;
1463 q = p; p += 4; /* q is placeholder for name length. */
1465 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1466 SIVAL(p,0,ea_size); /* Extended attributes */
1469 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1473 SIVAL(p,0,0); /* Ensure any padding is null. */
1474 len = PTR_DIFF(p, pdata);
1475 len = (len + 3) & ~3;
1480 case SMB_FIND_FILE_NAMES_INFO:
1481 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1483 SIVAL(p,0,reskey); p += 4;
1485 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1486 acl on a dir (tridge) */
1487 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1490 SIVAL(p,0,0); /* Ensure any padding is null. */
1491 len = PTR_DIFF(p, pdata);
1492 len = (len + 3) & ~3;
1497 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1498 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1500 SIVAL(p,0,reskey); p += 4;
1501 put_long_date_timespec(p,create_date_ts); p += 8;
1502 put_long_date_timespec(p,adate_ts); p += 8;
1503 put_long_date_timespec(p,mdate_ts); p += 8;
1504 put_long_date_timespec(p,mdate_ts); p += 8;
1505 SOFF_T(p,0,file_size); p += 8;
1506 SOFF_T(p,0,allocation_size); p += 8;
1507 SIVAL(p,0,nt_extmode); p += 4;
1508 q = p; p += 4; /* q is placeholder for name length. */
1510 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1511 SIVAL(p,0,ea_size); /* Extended attributes */
1514 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1515 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1516 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1517 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1520 SIVAL(p,0,0); /* Ensure any padding is null. */
1521 len = PTR_DIFF(p, pdata);
1522 len = (len + 3) & ~3;
1527 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1528 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1529 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1531 SIVAL(p,0,reskey); p += 4;
1532 put_long_date_timespec(p,create_date_ts); p += 8;
1533 put_long_date_timespec(p,adate_ts); p += 8;
1534 put_long_date_timespec(p,mdate_ts); p += 8;
1535 put_long_date_timespec(p,mdate_ts); p += 8;
1536 SOFF_T(p,0,file_size); p += 8;
1537 SOFF_T(p,0,allocation_size); p += 8;
1538 SIVAL(p,0,nt_extmode); p += 4;
1539 q = p; p += 4; /* q is placeholder for name length */
1541 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1542 SIVAL(p,0,ea_size); /* Extended attributes */
1545 /* Clear the short name buffer. This is
1546 * IMPORTANT as not doing so will trigger
1547 * a Win2k client bug. JRA.
1549 if (!was_8_3 && check_mangled_names) {
1550 pstring mangled_name;
1551 pstrcpy(mangled_name, fname);
1552 mangle_map(mangled_name,True,True,
1554 mangled_name[12] = 0;
1555 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1558 memset(p + 2 + len,'\0',24 - len);
1565 SSVAL(p,0,0); p += 2; /* Reserved ? */
1566 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1567 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1568 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1571 SIVAL(p,0,0); /* Ensure any padding is null. */
1572 len = PTR_DIFF(p, pdata);
1573 len = (len + 3) & ~3;
1578 /* CIFS UNIX Extension. */
1580 case SMB_FIND_FILE_UNIX:
1581 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1583 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1585 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1586 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1589 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1592 put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
1593 put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
1594 put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
1597 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1601 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1605 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1608 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1612 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1616 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1619 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1623 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1627 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1629 SIVAL(p,0,0); /* Ensure any padding is null. */
1631 len = PTR_DIFF(p, pdata);
1632 len = (len + 3) & ~3;
1633 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1635 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1644 if (PTR_DIFF(p,pdata) > space_remaining) {
1645 /* Move the dirptr back to prev_dirpos */
1646 dptr_SeekDir(conn->dirptr, prev_dirpos);
1647 *out_of_space = True;
1648 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1649 return False; /* Not finished - just out of space */
1652 /* Setup the last entry pointer, as an offset from base_data */
1653 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1654 /* Advance the data pointer to the next slot */
1660 /****************************************************************************
1661 Reply to a TRANS2_FINDFIRST.
1662 ****************************************************************************/
1664 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1665 char **pparams, int total_params, char **ppdata, int total_data,
1666 unsigned int max_data_bytes)
1668 /* We must be careful here that we don't return more than the
1669 allowed number of data bytes. If this means returning fewer than
1670 maxentries then so be it. We assume that the redirector has
1671 enough room for the fixed number of parameter bytes it has
1673 char *params = *pparams;
1674 char *pdata = *ppdata;
1677 uint16 findfirst_flags;
1678 BOOL close_after_first;
1680 BOOL requires_resume_key;
1685 int last_entry_off=0;
1689 BOOL finished = False;
1690 BOOL dont_descend = False;
1691 BOOL out_of_space = False;
1692 int space_remaining;
1693 BOOL mask_contains_wcard = False;
1694 SMB_STRUCT_STAT sbuf;
1695 TALLOC_CTX *ea_ctx = NULL;
1696 struct ea_list *ea_list = NULL;
1697 NTSTATUS ntstatus = NT_STATUS_OK;
1699 if (total_params < 13) {
1700 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1703 dirtype = SVAL(params,0);
1704 maxentries = SVAL(params,2);
1705 findfirst_flags = SVAL(params,4);
1706 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1707 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1708 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1709 info_level = SVAL(params,6);
1711 *directory = *mask = 0;
1713 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1714 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1715 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1716 info_level, max_data_bytes));
1719 /* W2K3 seems to treat zero as 1. */
1723 switch (info_level) {
1724 case SMB_FIND_INFO_STANDARD:
1725 case SMB_FIND_EA_SIZE:
1726 case SMB_FIND_EA_LIST:
1727 case SMB_FIND_FILE_DIRECTORY_INFO:
1728 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1729 case SMB_FIND_FILE_NAMES_INFO:
1730 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1731 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1732 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1734 case SMB_FIND_FILE_UNIX:
1735 if (!lp_unix_extensions()) {
1736 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1743 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1744 if (!NT_STATUS_IS_OK(ntstatus)) {
1745 return ERROR_NT(ntstatus);
1748 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1750 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1751 if (!NT_STATUS_IS_OK(ntstatus)) {
1752 return ERROR_NT(ntstatus);
1754 ntstatus = check_name(conn, directory);
1755 if (!NT_STATUS_IS_OK(ntstatus)) {
1756 return ERROR_NT(ntstatus);
1759 p = strrchr_m(directory,'/');
1761 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1762 if((directory[0] == '.') && (directory[1] == '\0')) {
1764 mask_contains_wcard = True;
1766 pstrcpy(mask,directory);
1768 pstrcpy(directory,"./");
1774 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1776 if (info_level == SMB_FIND_EA_LIST) {
1779 if (total_data < 4) {
1780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1783 ea_size = IVAL(pdata,0);
1784 if (ea_size != total_data) {
1785 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1786 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1790 if (!lp_ea_support(SNUM(conn))) {
1791 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1794 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1795 return ERROR_NT(NT_STATUS_NO_MEMORY);
1798 /* Pull out the list of names. */
1799 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1801 talloc_destroy(ea_ctx);
1802 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1806 *ppdata = (char *)SMB_REALLOC(
1807 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1808 if(*ppdata == NULL ) {
1809 talloc_destroy(ea_ctx);
1810 return ERROR_NT(NT_STATUS_NO_MEMORY);
1814 /* Realloc the params space */
1815 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1816 if (*pparams == NULL) {
1817 talloc_destroy(ea_ctx);
1818 return ERROR_NT(NT_STATUS_NO_MEMORY);
1822 /* Save the wildcard match and attribs we are using on this directory -
1823 needed as lanman2 assumes these are being saved between calls */
1825 ntstatus = dptr_create(conn,
1829 SVAL(inbuf,smb_pid),
1831 mask_contains_wcard,
1835 if (!NT_STATUS_IS_OK(ntstatus)) {
1836 talloc_destroy(ea_ctx);
1837 return ERROR_NT(ntstatus);
1840 dptr_num = dptr_dnum(conn->dirptr);
1841 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1843 /* We don't need to check for VOL here as this is returned by
1844 a different TRANS2 call. */
1846 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1847 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1848 dont_descend = True;
1851 space_remaining = max_data_bytes;
1852 out_of_space = False;
1854 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1855 BOOL got_exact_match = False;
1857 /* this is a heuristic to avoid seeking the dirptr except when
1858 absolutely necessary. It allows for a filename of about 40 chars */
1859 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1860 out_of_space = True;
1863 finished = !get_lanman2_dir_entry(conn,
1865 mask,dirtype,info_level,
1866 requires_resume_key,dont_descend,
1867 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1868 &last_entry_off, ea_list, ea_ctx);
1871 if (finished && out_of_space)
1874 if (!finished && !out_of_space)
1878 * As an optimisation if we know we aren't looking
1879 * for a wildcard name (ie. the name matches the wildcard exactly)
1880 * then we can finish on any (first) match.
1881 * This speeds up large directory searches. JRA.
1887 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1890 talloc_destroy(ea_ctx);
1892 /* Check if we can close the dirptr */
1893 if(close_after_first || (finished && close_if_end)) {
1894 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1895 dptr_close(&dptr_num);
1899 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1900 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1901 * the protocol level is less than NT1. Tested with smbclient. JRA.
1902 * This should fix the OS/2 client bug #2335.
1905 if(numentries == 0) {
1906 dptr_close(&dptr_num);
1907 if (Protocol < PROTOCOL_NT1) {
1908 return ERROR_DOS(ERRDOS,ERRnofiles);
1910 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1914 /* At this point pdata points to numentries directory entries. */
1916 /* Set up the return parameter block */
1917 SSVAL(params,0,dptr_num);
1918 SSVAL(params,2,numentries);
1919 SSVAL(params,4,finished);
1920 SSVAL(params,6,0); /* Never an EA error */
1921 SSVAL(params,8,last_entry_off);
1923 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1925 if ((! *directory) && dptr_path(dptr_num))
1926 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1928 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1929 smb_fn_name(CVAL(inbuf,smb_com)),
1930 mask, directory, dirtype, numentries ) );
1933 * Force a name mangle here to ensure that the
1934 * mask as an 8.3 name is top of the mangled cache.
1935 * The reasons for this are subtle. Don't remove
1936 * this code unless you know what you are doing
1937 * (see PR#13758). JRA.
1940 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1941 mangle_map(mask, True, True, conn->params);
1946 /****************************************************************************
1947 Reply to a TRANS2_FINDNEXT.
1948 ****************************************************************************/
1950 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1951 char **pparams, int total_params, char **ppdata, int total_data,
1952 unsigned int max_data_bytes)
1954 /* We must be careful here that we don't return more than the
1955 allowed number of data bytes. If this means returning fewer than
1956 maxentries then so be it. We assume that the redirector has
1957 enough room for the fixed number of parameter bytes it has
1959 char *params = *pparams;
1960 char *pdata = *ppdata;
1965 uint16 findnext_flags;
1966 BOOL close_after_request;
1968 BOOL requires_resume_key;
1970 BOOL mask_contains_wcard = False;
1971 pstring resume_name;
1977 int i, last_entry_off=0;
1978 BOOL finished = False;
1979 BOOL dont_descend = False;
1980 BOOL out_of_space = False;
1981 int space_remaining;
1982 TALLOC_CTX *ea_ctx = NULL;
1983 struct ea_list *ea_list = NULL;
1984 NTSTATUS ntstatus = NT_STATUS_OK;
1986 if (total_params < 13) {
1987 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1990 dptr_num = SVAL(params,0);
1991 maxentries = SVAL(params,2);
1992 info_level = SVAL(params,4);
1993 resume_key = IVAL(params,6);
1994 findnext_flags = SVAL(params,10);
1995 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1996 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1997 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1998 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2000 *mask = *directory = *resume_name = 0;
2002 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2003 if (!NT_STATUS_IS_OK(ntstatus)) {
2004 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2005 complain (it thinks we're asking for the directory above the shared
2006 path or an invalid name). Catch this as the resume name is only compared, never used in
2007 a file access. JRA. */
2008 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2009 pstrcpy(resume_name, "..");
2010 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2011 pstrcpy(resume_name, ".");
2013 return ERROR_NT(ntstatus);
2017 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2018 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2019 resume_key = %d resume name = %s continue=%d level = %d\n",
2020 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2021 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2024 /* W2K3 seems to treat zero as 1. */
2028 switch (info_level) {
2029 case SMB_FIND_INFO_STANDARD:
2030 case SMB_FIND_EA_SIZE:
2031 case SMB_FIND_EA_LIST:
2032 case SMB_FIND_FILE_DIRECTORY_INFO:
2033 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2034 case SMB_FIND_FILE_NAMES_INFO:
2035 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2036 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2039 case SMB_FIND_FILE_UNIX:
2040 if (!lp_unix_extensions()) {
2041 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2045 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2048 if (info_level == SMB_FIND_EA_LIST) {
2051 if (total_data < 4) {
2052 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2055 ea_size = IVAL(pdata,0);
2056 if (ea_size != total_data) {
2057 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2058 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2059 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2062 if (!lp_ea_support(SNUM(conn))) {
2063 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2066 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2067 return ERROR_NT(NT_STATUS_NO_MEMORY);
2070 /* Pull out the list of names. */
2071 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2073 talloc_destroy(ea_ctx);
2074 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2078 *ppdata = (char *)SMB_REALLOC(
2079 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2080 if(*ppdata == NULL) {
2081 talloc_destroy(ea_ctx);
2082 return ERROR_NT(NT_STATUS_NO_MEMORY);
2087 /* Realloc the params space */
2088 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2089 if(*pparams == NULL ) {
2090 talloc_destroy(ea_ctx);
2091 return ERROR_NT(NT_STATUS_NO_MEMORY);
2096 /* Check that the dptr is valid */
2097 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2098 talloc_destroy(ea_ctx);
2099 return ERROR_DOS(ERRDOS,ERRnofiles);
2102 string_set(&conn->dirpath,dptr_path(dptr_num));
2104 /* Get the wildcard mask from the dptr */
2105 if((p = dptr_wcard(dptr_num))== NULL) {
2106 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2107 talloc_destroy(ea_ctx);
2108 return ERROR_DOS(ERRDOS,ERRnofiles);
2112 pstrcpy(directory,conn->dirpath);
2114 /* Get the attr mask from the dptr */
2115 dirtype = dptr_attr(dptr_num);
2117 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2118 dptr_num, mask, dirtype,
2120 dptr_TellDir(conn->dirptr)));
2122 /* We don't need to check for VOL here as this is returned by
2123 a different TRANS2 call. */
2125 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2126 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2127 dont_descend = True;
2130 space_remaining = max_data_bytes;
2131 out_of_space = False;
2134 * Seek to the correct position. We no longer use the resume key but
2135 * depend on the last file name instead.
2138 if(*resume_name && !continue_bit) {
2141 long current_pos = 0;
2143 * Remember, mangle_map is called by
2144 * get_lanman2_dir_entry(), so the resume name
2145 * could be mangled. Ensure we check the unmangled name.
2148 if (mangle_is_mangled(resume_name, conn->params)) {
2149 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2154 * Fix for NT redirector problem triggered by resume key indexes
2155 * changing between directory scans. We now return a resume key of 0
2156 * and instead look for the filename to continue from (also given
2157 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2158 * findfirst/findnext (as is usual) then the directory pointer
2159 * should already be at the correct place.
2162 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2163 } /* end if resume_name && !continue_bit */
2165 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2166 BOOL got_exact_match = False;
2168 /* this is a heuristic to avoid seeking the dirptr except when
2169 absolutely necessary. It allows for a filename of about 40 chars */
2170 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2171 out_of_space = True;
2174 finished = !get_lanman2_dir_entry(conn,
2176 mask,dirtype,info_level,
2177 requires_resume_key,dont_descend,
2178 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2179 &last_entry_off, ea_list, ea_ctx);
2182 if (finished && out_of_space)
2185 if (!finished && !out_of_space)
2189 * As an optimisation if we know we aren't looking
2190 * for a wildcard name (ie. the name matches the wildcard exactly)
2191 * then we can finish on any (first) match.
2192 * This speeds up large directory searches. JRA.
2198 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2201 talloc_destroy(ea_ctx);
2203 /* Check if we can close the dirptr */
2204 if(close_after_request || (finished && close_if_end)) {
2205 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2206 dptr_close(&dptr_num); /* This frees up the saved mask */
2209 /* Set up the return parameter block */
2210 SSVAL(params,0,numentries);
2211 SSVAL(params,2,finished);
2212 SSVAL(params,4,0); /* Never an EA error */
2213 SSVAL(params,6,last_entry_off);
2215 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2217 if ((! *directory) && dptr_path(dptr_num))
2218 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2220 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2221 smb_fn_name(CVAL(inbuf,smb_com)),
2222 mask, directory, dirtype, numentries ) );
2227 /****************************************************************************
2228 Reply to a TRANS2_QFSINFO (query filesystem info).
2229 ****************************************************************************/
2231 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2232 char **pparams, int total_params, char **ppdata, int total_data,
2233 unsigned int max_data_bytes)
2235 char *pdata = *ppdata;
2236 char *params = *pparams;
2240 char *vname = volume_label(SNUM(conn));
2241 int snum = SNUM(conn);
2242 char *fstype = lp_fstype(SNUM(conn));
2245 if (total_params < 2) {
2246 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2249 info_level = SVAL(params,0);
2251 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2253 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2254 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2255 return ERROR_DOS(ERRSRV,ERRinvdevice);
2258 *ppdata = (char *)SMB_REALLOC(
2259 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2260 if (*ppdata == NULL ) {
2261 return ERROR_NT(NT_STATUS_NO_MEMORY);
2265 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2267 switch (info_level) {
2268 case SMB_INFO_ALLOCATION:
2270 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2272 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2273 return(UNIXERROR(ERRHRD,ERRgeneral));
2276 block_size = lp_block_size(snum);
2277 if (bsize < block_size) {
2278 SMB_BIG_UINT factor = block_size/bsize;
2283 if (bsize > block_size) {
2284 SMB_BIG_UINT factor = bsize/block_size;
2289 bytes_per_sector = 512;
2290 sectors_per_unit = bsize/bytes_per_sector;
2292 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2293 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2294 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2296 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2297 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2298 SIVAL(pdata,l1_cUnit,dsize);
2299 SIVAL(pdata,l1_cUnitAvail,dfree);
2300 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2304 case SMB_INFO_VOLUME:
2305 /* Return volume name */
2307 * Add volume serial number - hash of a combination of
2308 * the called hostname and the service name.
2310 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2312 * Win2k3 and previous mess this up by sending a name length
2313 * one byte short. I believe only older clients (OS/2 Win9x) use
2314 * this call so try fixing this by adding a terminating null to
2315 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2317 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2318 SCVAL(pdata,l2_vol_cch,len);
2319 data_len = l2_vol_szVolLabel + len;
2320 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2321 (unsigned)st.st_ctime, len, vname));
2324 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2325 case SMB_FS_ATTRIBUTE_INFORMATION:
2328 #if defined(HAVE_SYS_QUOTAS)
2329 quota_flag = FILE_VOLUME_QUOTAS;
2332 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2333 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2334 quota_flag); /* FS ATTRIBUTES */
2336 SIVAL(pdata,4,255); /* Max filename component length */
2337 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2338 and will think we can't do long filenames */
2339 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2341 data_len = 12 + len;
2344 case SMB_QUERY_FS_LABEL_INFO:
2345 case SMB_FS_LABEL_INFORMATION:
2346 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2351 case SMB_QUERY_FS_VOLUME_INFO:
2352 case SMB_FS_VOLUME_INFORMATION:
2355 * Add volume serial number - hash of a combination of
2356 * the called hostname and the service name.
2358 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2359 (str_checksum(get_local_machine_name())<<16));
2361 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2362 SIVAL(pdata,12,len);
2364 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2365 (int)strlen(vname),vname, lp_servicename(snum)));
2368 case SMB_QUERY_FS_SIZE_INFO:
2369 case SMB_FS_SIZE_INFORMATION:
2371 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2373 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2374 return(UNIXERROR(ERRHRD,ERRgeneral));
2376 block_size = lp_block_size(snum);
2377 if (bsize < block_size) {
2378 SMB_BIG_UINT factor = block_size/bsize;
2383 if (bsize > block_size) {
2384 SMB_BIG_UINT factor = bsize/block_size;
2389 bytes_per_sector = 512;
2390 sectors_per_unit = bsize/bytes_per_sector;
2391 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2392 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2393 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2394 SBIG_UINT(pdata,0,dsize);
2395 SBIG_UINT(pdata,8,dfree);
2396 SIVAL(pdata,16,sectors_per_unit);
2397 SIVAL(pdata,20,bytes_per_sector);
2401 case SMB_FS_FULL_SIZE_INFORMATION:
2403 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2405 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2406 return(UNIXERROR(ERRHRD,ERRgeneral));
2408 block_size = lp_block_size(snum);
2409 if (bsize < block_size) {
2410 SMB_BIG_UINT factor = block_size/bsize;
2415 if (bsize > block_size) {
2416 SMB_BIG_UINT factor = bsize/block_size;
2421 bytes_per_sector = 512;
2422 sectors_per_unit = bsize/bytes_per_sector;
2423 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2424 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2425 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2426 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2427 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2428 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2429 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2430 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2434 case SMB_QUERY_FS_DEVICE_INFO:
2435 case SMB_FS_DEVICE_INFORMATION:
2437 SIVAL(pdata,0,0); /* dev type */
2438 SIVAL(pdata,4,0); /* characteristics */
2441 #ifdef HAVE_SYS_QUOTAS
2442 case SMB_FS_QUOTA_INFORMATION:
2444 * what we have to send --metze:
2446 * Unknown1: 24 NULL bytes
2447 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2448 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2449 * Quota Flags: 2 byte :
2450 * Unknown3: 6 NULL bytes
2454 * details for Quota Flags:
2456 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2457 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2458 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2459 * 0x0001 Enable Quotas: enable quota for this fs
2463 /* we need to fake up a fsp here,
2464 * because its not send in this call
2467 SMB_NTQUOTA_STRUCT quotas;
2470 ZERO_STRUCT(quotas);
2476 if (current_user.ut.uid != 0) {
2477 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2478 lp_servicename(SNUM(conn)),conn->user));
2479 return ERROR_DOS(ERRDOS,ERRnoaccess);
2482 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2483 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2484 return ERROR_DOS(ERRSRV,ERRerror);
2489 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2491 /* Unknown1 24 NULL bytes*/
2492 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2493 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2494 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2496 /* Default Soft Quota 8 bytes */
2497 SBIG_UINT(pdata,24,quotas.softlim);
2499 /* Default Hard Quota 8 bytes */
2500 SBIG_UINT(pdata,32,quotas.hardlim);
2502 /* Quota flag 2 bytes */
2503 SSVAL(pdata,40,quotas.qflags);
2505 /* Unknown3 6 NULL bytes */
2511 #endif /* HAVE_SYS_QUOTAS */
2512 case SMB_FS_OBJECTID_INFORMATION:
2517 * Query the version and capabilities of the CIFS UNIX extensions
2521 case SMB_QUERY_CIFS_UNIX_INFO:
2522 if (!lp_unix_extensions()) {
2523 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2526 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2527 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2528 /* We have POSIX ACLs, pathname and locking capability. */
2529 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2530 CIFS_UNIX_POSIX_ACLS_CAP|
2531 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2532 CIFS_UNIX_FCNTL_LOCKS_CAP|
2533 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2536 case SMB_QUERY_POSIX_FS_INFO:
2539 vfs_statvfs_struct svfs;
2541 if (!lp_unix_extensions()) {
2542 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2545 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2549 SIVAL(pdata,0,svfs.OptimalTransferSize);
2550 SIVAL(pdata,4,svfs.BlockSize);
2551 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2552 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2553 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2554 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2555 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2556 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2557 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2559 } else if (rc == EOPNOTSUPP) {
2560 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2561 #endif /* EOPNOTSUPP */
2563 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2564 return ERROR_DOS(ERRSRV,ERRerror);
2569 case SMB_MAC_QUERY_FS_INFO:
2571 * Thursby MAC extension... ONLY on NTFS filesystems
2572 * once we do streams then we don't need this
2574 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2576 SIVAL(pdata,84,0x100); /* Don't support mac... */
2581 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2585 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2587 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2592 /****************************************************************************
2593 Reply to a TRANS2_SETFSINFO (set filesystem info).
2594 ****************************************************************************/
2596 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2597 char **pparams, int total_params, char **ppdata, int total_data,
2598 unsigned int max_data_bytes)
2600 char *pdata = *ppdata;
2601 char *params = *pparams;
2605 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2608 if (total_params < 4) {
2609 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2611 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2614 info_level = SVAL(params,2);
2616 switch(info_level) {
2617 case SMB_SET_CIFS_UNIX_INFO:
2619 uint16 client_unix_major;
2620 uint16 client_unix_minor;
2621 uint32 client_unix_cap_low;
2622 uint32 client_unix_cap_high;
2624 if (!lp_unix_extensions()) {
2625 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2628 /* There should be 12 bytes of capabilities set. */
2629 if (total_data < 8) {
2630 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2632 client_unix_major = SVAL(pdata,0);
2633 client_unix_minor = SVAL(pdata,2);
2634 client_unix_cap_low = IVAL(pdata,4);
2635 client_unix_cap_high = IVAL(pdata,8);
2636 /* Just print these values for now. */
2637 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2638 cap_low = 0x%x, cap_high = 0x%x\n",
2639 (unsigned int)client_unix_major,
2640 (unsigned int)client_unix_minor,
2641 (unsigned int)client_unix_cap_low,
2642 (unsigned int)client_unix_cap_high ));
2644 /* Here is where we must switch to posix pathname processing... */
2645 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2646 lp_set_posix_pathnames();
2647 mangle_change_to_posix();
2650 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2651 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2652 /* Client that knows how to do posix locks,
2653 * but not posix open/mkdir operations. Set a
2654 * default type for read/write checks. */
2656 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2661 case SMB_FS_QUOTA_INFORMATION:
2663 files_struct *fsp = NULL;
2664 SMB_NTQUOTA_STRUCT quotas;
2666 ZERO_STRUCT(quotas);
2669 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2670 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2671 lp_servicename(SNUM(conn)),conn->user));
2672 return ERROR_DOS(ERRSRV,ERRaccess);
2675 /* note: normaly there're 48 bytes,
2676 * but we didn't use the last 6 bytes for now
2679 fsp = file_fsp(params,0);
2680 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2681 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2682 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2685 if (total_data < 42) {
2686 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2691 /* unknown_1 24 NULL bytes in pdata*/
2693 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2694 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2695 #ifdef LARGE_SMB_OFF_T
2696 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2697 #else /* LARGE_SMB_OFF_T */
2698 if ((IVAL(pdata,28) != 0)&&
2699 ((quotas.softlim != 0xFFFFFFFF)||
2700 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2701 /* more than 32 bits? */
2702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2704 #endif /* LARGE_SMB_OFF_T */
2706 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2707 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2708 #ifdef LARGE_SMB_OFF_T
2709 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2710 #else /* LARGE_SMB_OFF_T */
2711 if ((IVAL(pdata,36) != 0)&&
2712 ((quotas.hardlim != 0xFFFFFFFF)||
2713 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2714 /* more than 32 bits? */
2715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2717 #endif /* LARGE_SMB_OFF_T */
2719 /* quota_flags 2 bytes **/
2720 quotas.qflags = SVAL(pdata,40);
2722 /* unknown_2 6 NULL bytes follow*/
2724 /* now set the quotas */
2725 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2726 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2727 return ERROR_DOS(ERRSRV,ERRerror);
2733 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2735 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2740 * sending this reply works fine,
2741 * but I'm not sure it's the same
2742 * like windows do...
2745 outsize = set_message(outbuf,10,0,True);
2750 #if defined(HAVE_POSIX_ACLS)
2751 /****************************************************************************
2752 Utility function to count the number of entries in a POSIX acl.
2753 ****************************************************************************/
2755 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2757 unsigned int ace_count = 0;
2758 int entry_id = SMB_ACL_FIRST_ENTRY;
2759 SMB_ACL_ENTRY_T entry;
2761 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2763 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2764 entry_id = SMB_ACL_NEXT_ENTRY;
2771 /****************************************************************************
2772 Utility function to marshall a POSIX acl into wire format.
2773 ****************************************************************************/
2775 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2777 int entry_id = SMB_ACL_FIRST_ENTRY;
2778 SMB_ACL_ENTRY_T entry;
2780 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2781 SMB_ACL_TAG_T tagtype;
2782 SMB_ACL_PERMSET_T permset;
2783 unsigned char perms = 0;
2784 unsigned int own_grp;
2787 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2788 entry_id = SMB_ACL_NEXT_ENTRY;
2791 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2792 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2796 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2797 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2801 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2802 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2803 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2805 SCVAL(pdata,1,perms);
2808 case SMB_ACL_USER_OBJ:
2809 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2810 own_grp = (unsigned int)pst->st_uid;
2811 SIVAL(pdata,2,own_grp);
2816 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2818 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2820 own_grp = (unsigned int)*puid;
2821 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2822 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2823 SIVAL(pdata,2,own_grp);
2827 case SMB_ACL_GROUP_OBJ:
2828 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2829 own_grp = (unsigned int)pst->st_gid;
2830 SIVAL(pdata,2,own_grp);
2835 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2837 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2839 own_grp = (unsigned int)*pgid;
2840 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2841 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2842 SIVAL(pdata,2,own_grp);
2847 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2848 SIVAL(pdata,2,0xFFFFFFFF);
2849 SIVAL(pdata,6,0xFFFFFFFF);
2852 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2853 SIVAL(pdata,2,0xFFFFFFFF);
2854 SIVAL(pdata,6,0xFFFFFFFF);
2857 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2860 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2867 /****************************************************************************
2868 Store the FILE_UNIX_BASIC info.
2869 ****************************************************************************/
2871 static char *store_file_unix_basic(connection_struct *conn,
2874 SMB_STRUCT_STAT *psbuf)
2876 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2877 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2879 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
2882 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2885 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
2886 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
2887 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
2890 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
2894 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
2898 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
2901 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
2905 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
2909 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
2912 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
2916 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
2923 /****************************************************************************
2924 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2925 file name or file id).
2926 ****************************************************************************/
2928 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2929 unsigned int tran_call,
2930 char **pparams, int total_params, char **ppdata, int total_data,
2931 unsigned int max_data_bytes)
2933 char *params = *pparams;
2934 char *pdata = *ppdata;
2938 SMB_OFF_T file_size=0;
2939 SMB_BIG_UINT allocation_size=0;
2940 unsigned int data_size = 0;
2941 unsigned int param_size = 2;
2942 SMB_STRUCT_STAT sbuf;
2943 pstring fname, dos_fname;
2948 BOOL delete_pending = False;
2950 time_t create_time, mtime, atime;
2951 struct timespec create_time_ts, mtime_ts, atime_ts;
2952 files_struct *fsp = NULL;
2953 TALLOC_CTX *data_ctx = NULL;
2954 struct ea_list *ea_list = NULL;
2955 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2956 char *lock_data = NULL;
2959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2963 if (tran_call == TRANSACT2_QFILEINFO) {
2964 if (total_params < 4) {
2965 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2968 fsp = file_fsp(params,0);
2969 info_level = SVAL(params,2);
2971 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2973 if(fsp && (fsp->fake_file_handle)) {
2975 * This is actually for the QUOTA_FAKE_FILE --metze
2978 pstrcpy(fname, fsp->fsp_name);
2979 /* We know this name is ok, it's already passed the checks. */
2981 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2983 * This is actually a QFILEINFO on a directory
2984 * handle (returned from an NT SMB). NT5.0 seems
2985 * to do this call. JRA.
2987 /* We know this name is ok, it's already passed the checks. */
2988 pstrcpy(fname, fsp->fsp_name);
2990 if (INFO_LEVEL_IS_UNIX(info_level)) {
2991 /* Always do lstat for UNIX calls. */
2992 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2993 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2994 return UNIXERROR(ERRDOS,ERRbadpath);
2996 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2997 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2998 return UNIXERROR(ERRDOS,ERRbadpath);
3001 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3004 * Original code - this is an open file.
3006 CHECK_FSP(fsp,conn);
3008 pstrcpy(fname, fsp->fsp_name);
3009 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3010 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3011 return(UNIXERROR(ERRDOS,ERRbadfid));
3013 pos = fsp->fh->position_information;
3014 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3015 access_mask = fsp->access_mask;
3018 NTSTATUS status = NT_STATUS_OK;
3021 if (total_params < 7) {
3022 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3025 info_level = SVAL(params,0);
3027 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3029 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 return ERROR_NT(status);
3034 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
3036 status = unix_convert(conn, fname, False, NULL, &sbuf);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 return ERROR_NT(status);
3040 status = check_name(conn, fname);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3043 return ERROR_NT(status);
3046 if (INFO_LEVEL_IS_UNIX(info_level)) {
3047 /* Always do lstat for UNIX calls. */
3048 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3049 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3050 return UNIXERROR(ERRDOS,ERRbadpath);
3052 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3053 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3054 return UNIXERROR(ERRDOS,ERRbadpath);
3057 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3058 if (delete_pending) {
3059 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3063 nlink = sbuf.st_nlink;
3065 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3066 /* NTFS does not seem to count ".." */
3070 if ((nlink > 0) && delete_pending) {
3074 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3075 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3078 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3079 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3081 p = strrchr_m(fname,'/');
3087 mode = dos_mode(conn,fname,&sbuf);
3089 mode = FILE_ATTRIBUTE_NORMAL;
3091 fullpathname = fname;
3093 file_size = get_file_size(sbuf);
3095 /* Pull out any data sent here before we realloc. */
3096 switch (info_level) {
3097 case SMB_INFO_QUERY_EAS_FROM_LIST:
3099 /* Pull any EA list from the data portion. */
3102 if (total_data < 4) {
3103 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3105 ea_size = IVAL(pdata,0);
3107 if (total_data > 0 && ea_size != total_data) {
3108 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3109 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3110 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3113 if (!lp_ea_support(SNUM(conn))) {
3114 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3117 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3118 return ERROR_NT(NT_STATUS_NO_MEMORY);
3121 /* Pull out the list of names. */
3122 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3124 talloc_destroy(data_ctx);
3125 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3130 case SMB_QUERY_POSIX_LOCK:
3132 if (fsp == NULL || fsp->fh->fd == -1) {
3133 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3136 if (total_data != POSIX_LOCK_DATA_SIZE) {
3137 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3140 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3141 return ERROR_NT(NT_STATUS_NO_MEMORY);
3144 /* Copy the lock range data. */
3145 lock_data = (char *)talloc_memdup(
3146 data_ctx, pdata, total_data);
3148 talloc_destroy(data_ctx);
3149 return ERROR_NT(NT_STATUS_NO_MEMORY);
3156 *pparams = (char *)SMB_REALLOC(*pparams,2);
3157 if (*pparams == NULL) {
3158 talloc_destroy(data_ctx);
3159 return ERROR_NT(NT_STATUS_NO_MEMORY);
3163 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3164 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3165 if (*ppdata == NULL ) {
3166 talloc_destroy(data_ctx);
3167 return ERROR_NT(NT_STATUS_NO_MEMORY);
3171 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3172 mtime_ts = get_mtimespec(&sbuf);
3173 atime_ts = get_atimespec(&sbuf);
3175 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3178 if (!null_timespec(fsp->pending_modtime)) {
3179 /* the pending modtime overrides the current modtime */
3180 mtime_ts = fsp->pending_modtime;
3183 /* Do we have this path open ? */
3184 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3185 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3186 /* the pending modtime overrides the current modtime */
3187 mtime_ts = fsp->pending_modtime;
3189 if (fsp1 && fsp1->initial_allocation_size) {
3190 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3194 if (lp_dos_filetime_resolution(SNUM(conn))) {
3195 dos_filetime_timespec(&create_time_ts);
3196 dos_filetime_timespec(&mtime_ts);
3197 dos_filetime_timespec(&atime_ts);
3200 create_time = convert_timespec_to_time_t(create_time_ts);
3201 mtime = convert_timespec_to_time_t(mtime_ts);
3202 atime = convert_timespec_to_time_t(atime_ts);
3204 /* NT expects the name to be in an exact form of the *full*
3205 filename. See the trans2 torture test */
3206 if (strequal(base_name,".")) {
3207 pstrcpy(dos_fname, "\\");
3209 pstr_sprintf(dos_fname, "\\%s", fname);
3210 string_replace(dos_fname, '/', '\\');
3213 switch (info_level) {
3214 case SMB_INFO_STANDARD:
3215 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3217 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3218 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3219 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3220 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3221 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3222 SSVAL(pdata,l1_attrFile,mode);
3225 case SMB_INFO_QUERY_EA_SIZE:
3227 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3228 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3230 srv_put_dos_date2(pdata,0,create_time);
3231 srv_put_dos_date2(pdata,4,atime);
3232 srv_put_dos_date2(pdata,8,mtime); /* write time */
3233 SIVAL(pdata,12,(uint32)file_size);
3234 SIVAL(pdata,16,(uint32)allocation_size);
3235 SSVAL(pdata,20,mode);
3236 SIVAL(pdata,22,ea_size);
3240 case SMB_INFO_IS_NAME_VALID:
3241 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3242 if (tran_call == TRANSACT2_QFILEINFO) {
3243 /* os/2 needs this ? really ?*/
3244 return ERROR_DOS(ERRDOS,ERRbadfunc);
3250 case SMB_INFO_QUERY_EAS_FROM_LIST:
3252 size_t total_ea_len = 0;
3253 struct ea_list *ea_file_list = NULL;
3255 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3257 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3258 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3260 if (!ea_list || (total_ea_len > data_size)) {
3261 talloc_destroy(data_ctx);
3263 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3267 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3268 talloc_destroy(data_ctx);
3272 case SMB_INFO_QUERY_ALL_EAS:
3274 /* We have data_size bytes to put EA's into. */
3275 size_t total_ea_len = 0;
3277 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3279 data_ctx = talloc_init("ea_ctx");
3281 return ERROR_NT(NT_STATUS_NO_MEMORY);
3284 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3285 if (!ea_list || (total_ea_len > data_size)) {
3286 talloc_destroy(data_ctx);
3288 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3292 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3293 talloc_destroy(data_ctx);
3297 case SMB_FILE_BASIC_INFORMATION:
3298 case SMB_QUERY_FILE_BASIC_INFO:
3300 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3301 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3302 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3304 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3308 put_long_date_timespec(pdata,create_time_ts);
3309 put_long_date_timespec(pdata+8,atime_ts);
3310 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3311 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3312 SIVAL(pdata,32,mode);
3314 DEBUG(5,("SMB_QFBI - "));
3315 DEBUG(5,("create: %s ", ctime(&create_time)));
3316 DEBUG(5,("access: %s ", ctime(&atime)));
3317 DEBUG(5,("write: %s ", ctime(&mtime)));
3318 DEBUG(5,("change: %s ", ctime(&mtime)));
3319 DEBUG(5,("mode: %x\n", mode));
3322 case SMB_FILE_STANDARD_INFORMATION:
3323 case SMB_QUERY_FILE_STANDARD_INFO:
3325 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3327 SOFF_T(pdata,0,allocation_size);
3328 SOFF_T(pdata,8,file_size);
3329 SIVAL(pdata,16,nlink);
3330 SCVAL(pdata,20,delete_pending?1:0);
3331 SCVAL(pdata,21,(mode&aDIR)?1:0);
3332 SSVAL(pdata,22,0); /* Padding. */
3335 case SMB_FILE_EA_INFORMATION:
3336 case SMB_QUERY_FILE_EA_INFO:
3338 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3339 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3341 SIVAL(pdata,0,ea_size);
3345 /* Get the 8.3 name - used if NT SMB was negotiated. */
3346 case SMB_QUERY_FILE_ALT_NAME_INFO:
3347 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3351 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3352 pstrcpy(short_name,base_name);
3353 /* Mangle if not already 8.3 */
3354 if(!mangle_is_8_3(short_name, True, conn->params)) {
3355 mangle_map(short_name,True,True,conn->params);
3357 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3358 data_size = 4 + len;
3363 case SMB_QUERY_FILE_NAME_INFO:
3365 this must be *exactly* right for ACLs on mapped drives to work
3367 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3368 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3369 data_size = 4 + len;
3373 case SMB_FILE_ALLOCATION_INFORMATION:
3374 case SMB_QUERY_FILE_ALLOCATION_INFO:
3375 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3377 SOFF_T(pdata,0,allocation_size);
3380 case SMB_FILE_END_OF_FILE_INFORMATION:
3381 case SMB_QUERY_FILE_END_OF_FILEINFO:
3382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3384 SOFF_T(pdata,0,file_size);
3387 case SMB_QUERY_FILE_ALL_INFO:
3388 case SMB_FILE_ALL_INFORMATION:
3390 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3391 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3392 put_long_date_timespec(pdata,create_time_ts);
3393 put_long_date_timespec(pdata+8,atime_ts);
3394 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3395 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3396 SIVAL(pdata,32,mode);
3397 SIVAL(pdata,36,0); /* padding. */
3399 SOFF_T(pdata,0,allocation_size);
3400 SOFF_T(pdata,8,file_size);
3401 SIVAL(pdata,16,nlink);
3402 SCVAL(pdata,20,delete_pending);
3403 SCVAL(pdata,21,(mode&aDIR)?1:0);
3406 SIVAL(pdata,0,ea_size);
3407 pdata += 4; /* EA info */
3408 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3411 data_size = PTR_DIFF(pdata,(*ppdata));
3414 case SMB_FILE_INTERNAL_INFORMATION:
3415 /* This should be an index number - looks like
3418 I think this causes us to fail the IFSKIT
3419 BasicFileInformationTest. -tpot */
3421 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3422 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3423 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3427 case SMB_FILE_ACCESS_INFORMATION:
3428 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3429 SIVAL(pdata,0,access_mask);
3433 case SMB_FILE_NAME_INFORMATION:
3434 /* Pathname with leading '\'. */
3437 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3438 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3439 SIVAL(pdata,0,byte_len);
3440 data_size = 4 + byte_len;
3444 case SMB_FILE_DISPOSITION_INFORMATION:
3445 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3447 SCVAL(pdata,0,delete_pending);
3450 case SMB_FILE_POSITION_INFORMATION:
3451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3453 SOFF_T(pdata,0,pos);
3456 case SMB_FILE_MODE_INFORMATION:
3457 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3458 SIVAL(pdata,0,mode);
3462 case SMB_FILE_ALIGNMENT_INFORMATION:
3463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3464 SIVAL(pdata,0,0); /* No alignment needed. */
3470 * NT4 server just returns "invalid query" to this - if we try to answer
3471 * it then NTws gets a BSOD! (tridge).
3472 * W2K seems to want this. JRA.
3474 case SMB_QUERY_FILE_STREAM_INFO:
3476 case SMB_FILE_STREAM_INFORMATION:
3477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3481 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3482 SIVAL(pdata,0,0); /* ??? */
3483 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3484 SOFF_T(pdata,8,file_size);
3485 SIVAL(pdata,16,allocation_size);
3486 SIVAL(pdata,20,0); /* ??? */
3487 data_size = 24 + byte_len;
3491 case SMB_QUERY_COMPRESSION_INFO:
3492 case SMB_FILE_COMPRESSION_INFORMATION:
3493 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3494 SOFF_T(pdata,0,file_size);
3495 SIVAL(pdata,8,0); /* ??? */
3496 SIVAL(pdata,12,0); /* ??? */
3500 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3501 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3502 put_long_date_timespec(pdata,create_time_ts);
3503 put_long_date_timespec(pdata+8,atime_ts);
3504 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3505 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3506 SIVAL(pdata,32,allocation_size);
3507 SOFF_T(pdata,40,file_size);
3508 SIVAL(pdata,48,mode);
3509 SIVAL(pdata,52,0); /* ??? */
3513 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3514 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3515 SIVAL(pdata,0,mode);
3521 * CIFS UNIX Extensions.
3524 case SMB_QUERY_FILE_UNIX_BASIC:
3526 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3527 data_size = PTR_DIFF(pdata,(*ppdata));
3531 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3533 for (i=0; i<100; i++)
3534 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3540 case SMB_QUERY_FILE_UNIX_LINK:
3544 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3546 if(!S_ISLNK(sbuf.st_mode))
3547 return(UNIXERROR(ERRSRV,ERRbadlink));
3549 return(UNIXERROR(ERRDOS,ERRbadlink));
3551 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3553 return(UNIXERROR(ERRDOS,ERRnoaccess));
3555 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3557 data_size = PTR_DIFF(pdata,(*ppdata));
3562 #if defined(HAVE_POSIX_ACLS)
3563 case SMB_QUERY_POSIX_ACL:
3565 SMB_ACL_T file_acl = NULL;
3566 SMB_ACL_T def_acl = NULL;
3567 uint16 num_file_acls = 0;
3568 uint16 num_def_acls = 0;
3570 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3571 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3573 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3576 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3577 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3579 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3582 if (S_ISDIR(sbuf.st_mode)) {
3583 if (fsp && fsp->is_directory) {
3584 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3586 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3588 def_acl = free_empty_sys_acl(conn, def_acl);
3591 num_file_acls = count_acl_entries(conn, file_acl);
3592 num_def_acls = count_acl_entries(conn, def_acl);
3594 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3595 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3597 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3598 SMB_POSIX_ACL_HEADER_SIZE) ));
3600 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3603 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3605 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3608 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3609 SSVAL(pdata,2,num_file_acls);
3610 SSVAL(pdata,4,num_def_acls);
3611 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3613 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3616 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3618 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3620 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3622 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3625 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3627 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3631 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3634 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3636 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3642 case SMB_QUERY_POSIX_LOCK:
3644 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3646 SMB_BIG_UINT offset;
3648 enum brl_type lock_type;
3650 if (total_data != POSIX_LOCK_DATA_SIZE) {
3651 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3654 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3655 case POSIX_LOCK_TYPE_READ:
3656 lock_type = READ_LOCK;
3658 case POSIX_LOCK_TYPE_WRITE:
3659 lock_type = WRITE_LOCK;
3661 case POSIX_LOCK_TYPE_UNLOCK:
3663 /* There's no point in asking for an unlock... */
3664 talloc_destroy(data_ctx);
3665 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3668 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3669 #if defined(HAVE_LONGLONG)
3670 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3671 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3672 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3673 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3674 #else /* HAVE_LONGLONG */
3675 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3676 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3677 #endif /* HAVE_LONGLONG */
3679 status = query_lock(fsp,
3686 if (ERROR_WAS_LOCK_DENIED(status)) {
3687 /* Here we need to report who has it locked... */
3688 data_size = POSIX_LOCK_DATA_SIZE;
3690 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3691 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3692 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3693 #if defined(HAVE_LONGLONG)
3694 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3695 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3696 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3697 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3698 #else /* HAVE_LONGLONG */
3699 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3700 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3701 #endif /* HAVE_LONGLONG */
3703 } else if (NT_STATUS_IS_OK(status)) {
3704 /* For success we just return a copy of what we sent
3705 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3706 data_size = POSIX_LOCK_DATA_SIZE;
3707 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3708 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3710 return ERROR_NT(status);
3716 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3719 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3724 /****************************************************************************
3725 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3727 ****************************************************************************/
3729 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3731 SMB_STRUCT_STAT sbuf1, sbuf2;
3732 pstring last_component_oldname;
3733 pstring last_component_newname;
3734 NTSTATUS status = NT_STATUS_OK;
3739 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3740 if (!NT_STATUS_IS_OK(status)) {
3744 status = check_name(conn, oldname);
3745 if (!NT_STATUS_IS_OK(status)) {
3749 /* source must already exist. */
3750 if (!VALID_STAT(sbuf1)) {
3751 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3754 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3755 if (!NT_STATUS_IS_OK(status)) {
3759 status = check_name(conn, newname);
3760 if (!NT_STATUS_IS_OK(status)) {
3764 /* Disallow if newname already exists. */
3765 if (VALID_STAT(sbuf2)) {
3766 return NT_STATUS_OBJECT_NAME_COLLISION;
3769 /* No links from a directory. */
3770 if (S_ISDIR(sbuf1.st_mode)) {
3771 return NT_STATUS_FILE_IS_A_DIRECTORY;
3774 /* Ensure this is within the share. */
3775 status = reduce_name(conn, oldname);
3776 if (!NT_STATUS_IS_OK(status)) {
3780 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3782 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3783 status = map_nt_error_from_unix(errno);
3784 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3785 nt_errstr(status), newname, oldname));
3791 /****************************************************************************
3792 Deal with setting the time from any of the setfilepathinfo functions.
3793 ****************************************************************************/
3795 static NTSTATUS smb_set_file_time(connection_struct *conn,
3798 const SMB_STRUCT_STAT *psbuf,
3799 struct timespec ts[2])
3802 FILE_NOTIFY_CHANGE_LAST_ACCESS
3803 |FILE_NOTIFY_CHANGE_LAST_WRITE;
3806 if (!VALID_STAT(*psbuf)) {
3807 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3810 /* get some defaults (no modifications) if any info is zero or -1. */
3811 if (null_timespec(ts[0])) {
3812 ts[0] = get_atimespec(psbuf);
3813 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3816 if (null_timespec(ts[1])) {
3817 ts[1] = get_mtimespec(psbuf);
3818 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3821 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
3822 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
3825 * Try and set the times of this file if
3826 * they are different from the current values.
3830 struct timespec mts = get_mtimespec(psbuf);
3831 struct timespec ats = get_atimespec(psbuf);
3832 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
3833 return NT_STATUS_OK;
3839 * This was a setfileinfo on an open file.
3840 * NT does this a lot. We also need to
3841 * set the time here, as it can be read by
3842 * FindFirst/FindNext and with the patch for bug #2045
3843 * in smbd/fileio.c it ensures that this timestamp is
3844 * kept sticky even after a write. We save the request
3845 * away and will set it on file close and after a write. JRA.
3848 if (!null_timespec(ts[1])) {
3849 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
3850 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
3851 fsp_set_pending_modtime(fsp, ts[1]);
3855 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3857 if(file_ntimes(conn, fname, ts)!=0) {
3858 return map_nt_error_from_unix(errno);
3861 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
3863 return NT_STATUS_OK;
3866 /****************************************************************************
3867 Deal with setting the dosmode from any of the setfilepathinfo functions.
3868 ****************************************************************************/
3870 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3872 SMB_STRUCT_STAT *psbuf,
3875 if (!VALID_STAT(*psbuf)) {
3876 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3880 if (S_ISDIR(psbuf->st_mode)) {
3887 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
3889 /* check the mode isn't different, before changing it */
3890 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
3892 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
3893 fname, (unsigned int)dosmode ));
3895 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
3896 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
3897 fname, strerror(errno)));
3898 return map_nt_error_from_unix(errno);
3901 return NT_STATUS_OK;
3904 /****************************************************************************
3905 Deal with setting the size from any of the setfilepathinfo functions.
3906 ****************************************************************************/
3908 static NTSTATUS smb_set_file_size(connection_struct *conn,
3911 SMB_STRUCT_STAT *psbuf,
3914 NTSTATUS status = NT_STATUS_OK;
3915 files_struct *new_fsp = NULL;
3917 if (!VALID_STAT(*psbuf)) {
3918 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3921 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
3923 if (size == get_file_size(*psbuf)) {
3924 return NT_STATUS_OK;
3927 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
3928 fname, (double)size ));
3930 if (fsp && fsp->fh->fd != -1) {
3931 /* Handle based call. */
3932 if (vfs_set_filelen(fsp, size) == -1) {
3933 return map_nt_error_from_unix(errno);
3935 return NT_STATUS_OK;
3938 status = open_file_ntcreate(conn, fname, psbuf,
3940 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3943 FILE_ATTRIBUTE_NORMAL,
3944 FORCE_OPLOCK_BREAK_TO_NONE,
3947 if (!NT_STATUS_IS_OK(status)) {
3948 /* NB. We check for open_was_deferred in the caller. */
3952 if (vfs_set_filelen(new_fsp, size) == -1) {
3953 status = map_nt_error_from_unix(errno);
3954 close_file(new_fsp,NORMAL_CLOSE);
3958 close_file(new_fsp,NORMAL_CLOSE);
3959 return NT_STATUS_OK;
3962 /****************************************************************************
3963 Deal with SMB_INFO_SET_EA.
3964 ****************************************************************************/
3966 static NTSTATUS smb_info_set_ea(connection_struct *conn,
3972 struct ea_list *ea_list = NULL;
3973 TALLOC_CTX *ctx = NULL;
3974 NTSTATUS status = NT_STATUS_OK;
3976 if (total_data < 10) {
3978 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3979 length. They seem to have no effect. Bug #3212. JRA */
3981 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3982 /* We're done. We only get EA info in this call. */
3983 return NT_STATUS_OK;
3986 return NT_STATUS_INVALID_PARAMETER;
3989 if (IVAL(pdata,0) > total_data) {
3990 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
3991 IVAL(pdata,0), (unsigned int)total_data));
3992 return NT_STATUS_INVALID_PARAMETER;
3995 ctx = talloc_init("SMB_INFO_SET_EA");
3997 return NT_STATUS_NO_MEMORY;
3999 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4001 talloc_destroy(ctx);
4002 return NT_STATUS_INVALID_PARAMETER;
4004 status = set_ea(conn, fsp, fname, ea_list);
4005 talloc_destroy(ctx);
4010 /****************************************************************************
4011 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4012 ****************************************************************************/
4014 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4019 SMB_STRUCT_STAT *psbuf)
4021 NTSTATUS status = NT_STATUS_OK;
4022 BOOL delete_on_close;
4025 if (total_data < 1) {
4026 return NT_STATUS_INVALID_PARAMETER;
4030 return NT_STATUS_INVALID_HANDLE;
4033 delete_on_close = (CVAL(pdata,0) ? True : False);
4034 dosmode = dos_mode(conn, fname, psbuf);
4036 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4037 "delete_on_close = %u\n",
4039 (unsigned int)dosmode,
4040 (unsigned int)delete_on_close ));
4042 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4044 if (!NT_STATUS_IS_OK(status)) {
4048 /* The set is across all open files on this dev/inode pair. */
4049 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4050 return NT_STATUS_ACCESS_DENIED;
4052 return NT_STATUS_OK;
4055 /****************************************************************************
4056 Deal with SMB_FILE_POSITION_INFORMATION.
4057 ****************************************************************************/
4059 static NTSTATUS smb_file_position_information(connection_struct *conn,
4064 SMB_BIG_UINT position_information;
4066 if (total_data < 8) {
4067 return NT_STATUS_INVALID_PARAMETER;
4071 /* Ignore on pathname based set. */
4072 return NT_STATUS_OK;
4075 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4076 #ifdef LARGE_SMB_OFF_T
4077 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4078 #else /* LARGE_SMB_OFF_T */
4079 if (IVAL(pdata,4) != 0) {
4080 /* more than 32 bits? */
4081 return NT_STATUS_INVALID_PARAMETER;
4083 #endif /* LARGE_SMB_OFF_T */
4085 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4086 fsp->fsp_name, (double)position_information ));
4087 fsp->fh->position_information = position_information;
4088 return NT_STATUS_OK;
4091 /****************************************************************************
4092 Deal with SMB_FILE_MODE_INFORMATION.
4093 ****************************************************************************/
4095 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4101 if (total_data < 4) {
4102 return NT_STATUS_INVALID_PARAMETER;
4104 mode = IVAL(pdata,0);
4105 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4106 return NT_STATUS_INVALID_PARAMETER;
4108 return NT_STATUS_OK;
4111 /****************************************************************************
4112 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4113 ****************************************************************************/
4115 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4121 pstring link_target;
4122 const char *newname = fname;
4123 NTSTATUS status = NT_STATUS_OK;
4125 /* Set a symbolic link. */
4126 /* Don't allow this if follow links is false. */
4128 if (total_data == 0) {
4129 return NT_STATUS_INVALID_PARAMETER;
4132 if (!lp_symlinks(SNUM(conn))) {
4133 return NT_STATUS_ACCESS_DENIED;
4136 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4138 /* !widelinks forces the target path to be within the share. */
4139 /* This means we can interpret the target as a pathname. */
4140 if (!lp_widelinks(SNUM(conn))) {
4142 char *last_dirp = NULL;
4144 unix_format(link_target);
4145 if (*link_target == '/') {
4146 /* No absolute paths allowed. */
4147 return NT_STATUS_ACCESS_DENIED;
4149 pstrcpy(rel_name, newname);
4150 last_dirp = strrchr_m(rel_name, '/');
4152 last_dirp[1] = '\0';
4154 pstrcpy(rel_name, "./");
4156 pstrcat(rel_name, link_target);
4158 status = check_name(conn, rel_name);
4159 if (!NT_STATUS_IS_OK(status)) {
4164 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4165 newname, link_target ));
4167 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4168 return map_nt_error_from_unix(errno);
4171 return NT_STATUS_OK;
4174 /****************************************************************************
4175 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4176 ****************************************************************************/
4178 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4186 NTSTATUS status = NT_STATUS_OK;
4188 /* Set a hard link. */
4189 if (total_data == 0) {
4190 return NT_STATUS_INVALID_PARAMETER;
4193 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4194 if (!NT_STATUS_IS_OK(status)) {
4198 RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
4200 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4203 return hardlink_internals(conn, oldname, fname);
4206 /****************************************************************************
4207 Deal with SMB_FILE_RENAME_INFORMATION.
4208 ****************************************************************************/
4210 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4219 /* uint32 root_fid; */ /* Not used */
4223 BOOL dest_has_wcard = False;
4224 NTSTATUS status = NT_STATUS_OK;
4227 if (total_data < 13) {
4228 return NT_STATUS_INVALID_PARAMETER;
4231 overwrite = (CVAL(pdata,0) ? True : False);
4232 /* root_fid = IVAL(pdata,4); */
4233 len = IVAL(pdata,8);
4235 if (len > (total_data - 12) || (len == 0)) {
4236 return NT_STATUS_INVALID_PARAMETER;
4239 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4240 if (!NT_STATUS_IS_OK(status)) {
4244 RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
4246 /* Check the new name has no '/' characters. */
4247 if (strchr_m(newname, '/')) {
4248 return NT_STATUS_NOT_SUPPORTED;
4251 /* Create the base directory. */
4252 pstrcpy(base_name, fname);
4253 p = strrchr_m(base_name, '/');
4257 /* Append the new name. */
4258 pstrcat(base_name, "/");
4259 pstrcat(base_name, newname);
4262 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4263 fsp->fnum, fsp->fsp_name, base_name ));
4264 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4266 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4268 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4274 /****************************************************************************
4275 Deal with SMB_SET_POSIX_ACL.
4276 ****************************************************************************/
4278 #if defined(HAVE_POSIX_ACLS)
4279 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4284 SMB_STRUCT_STAT *psbuf)
4286 uint16 posix_acl_version;
4287 uint16 num_file_acls;
4288 uint16 num_def_acls;
4289 BOOL valid_file_acls = True;
4290 BOOL valid_def_acls = True;
4292 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4293 return NT_STATUS_INVALID_PARAMETER;
4295 posix_acl_version = SVAL(pdata,0);
4296 num_file_acls = SVAL(pdata,2);
4297 num_def_acls = SVAL(pdata,4);
4299 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4300 valid_file_acls = False;
4304 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4305 valid_def_acls = False;
4309 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4310 return NT_STATUS_INVALID_PARAMETER;
4313 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4314 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4315 return NT_STATUS_INVALID_PARAMETER;
4318 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4319 fname ? fname : fsp->fsp_name,
4320 (unsigned int)num_file_acls,
4321 (unsigned int)num_def_acls));
4323 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4324 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4325 return map_nt_error_from_unix(errno);
4328 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4329 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4330 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4331 return map_nt_error_from_unix(errno);
4333 return NT_STATUS_OK;
4337 /****************************************************************************
4338 Deal with SMB_SET_POSIX_LOCK.
4339 ****************************************************************************/
4341 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4349 SMB_BIG_UINT offset;
4351 BOOL blocking_lock = False;
4352 enum brl_type lock_type;
4353 NTSTATUS status = NT_STATUS_OK;
4355 if (fsp == NULL || fsp->fh->fd == -1) {
4356 return NT_STATUS_INVALID_HANDLE;
4359 if (total_data != POSIX_LOCK_DATA_SIZE) {
4360 return NT_STATUS_INVALID_PARAMETER;
4363 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4364 case POSIX_LOCK_TYPE_READ:
4365 lock_type = READ_LOCK;
4367 case POSIX_LOCK_TYPE_WRITE:
4368 /* Return the right POSIX-mappable error code for files opened read-only. */
4369 if (!fsp->can_write) {
4370 return NT_STATUS_INVALID_HANDLE;
4372 lock_type = WRITE_LOCK;
4374 case POSIX_LOCK_TYPE_UNLOCK:
4375 lock_type = UNLOCK_LOCK;
4378 return NT_STATUS_INVALID_PARAMETER;
4381 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4382 blocking_lock = False;
4383 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4384 blocking_lock = True;
4386 return NT_STATUS_INVALID_PARAMETER;
4389 if (!lp_blocking_locks(SNUM(conn))) {
4390 blocking_lock = False;
4393 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4394 #if defined(HAVE_LONGLONG)
4395 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4396 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4397 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4398 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4399 #else /* HAVE_LONGLONG */
4400 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4401 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4402 #endif /* HAVE_LONGLONG */
4404 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4405 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4407 (unsigned int)lock_type,
4408 (unsigned int)lock_pid,
4412 if (lock_type == UNLOCK_LOCK) {
4413 status = do_unlock(fsp,
4419 struct byte_range_lock *br_lck = do_lock(fsp,
4428 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4430 * A blocking lock was requested. Package up
4431 * this smb into a queued request and push it
4432 * onto the blocking lock queue.
4434 if(push_blocking_lock_request(br_lck,
4437 -1, /* infinite timeout. */
4444 TALLOC_FREE(br_lck);
4448 TALLOC_FREE(br_lck);
4454 /****************************************************************************
4455 Deal with SMB_INFO_STANDARD.
4456 ****************************************************************************/
4458 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4463 const SMB_STRUCT_STAT *psbuf)
4465 struct timespec ts[2];
4467 if (total_data < 12) {
4468 return NT_STATUS_INVALID_PARAMETER;
4472 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4474 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4476 DEBUG(10,("smb_set_info_standard: file %s\n",
4477 fname ? fname : fsp->fsp_name ));
4479 return smb_set_file_time(conn,
4486 /****************************************************************************
4487 Deal with SMB_SET_FILE_BASIC_INFO.
4488 ****************************************************************************/
4490 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4495 SMB_STRUCT_STAT *psbuf)
4497 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4498 struct timespec write_time;
4499 struct timespec changed_time;
4501 struct timespec ts[2];
4502 NTSTATUS status = NT_STATUS_OK;
4504 if (total_data < 36) {
4505 return NT_STATUS_INVALID_PARAMETER;
4508 /* Set the attributes */
4509 dosmode = IVAL(pdata,32);
4510 status = smb_set_file_dosmode(conn,
4514 if (!NT_STATUS_IS_OK(status)) {
4518 /* Ignore create time at offset pdata. */
4521 ts[0] = interpret_long_date(pdata+8);
4523 write_time = interpret_long_date(pdata+16);
4524 changed_time = interpret_long_date(pdata+24);
4527 ts[1] = timespec_min(&write_time, &changed_time);
4529 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4533 /* Prefer a defined time to an undefined one. */
4534 if (null_timespec(ts[1])) {
4535 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4538 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4539 fname ? fname : fsp->fsp_name ));
4541 return smb_set_file_time(conn,
4548 /****************************************************************************
4549 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4550 ****************************************************************************/
4552 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4557 SMB_STRUCT_STAT *psbuf)
4559 SMB_BIG_UINT allocation_size = 0;
4560 NTSTATUS status = NT_STATUS_OK;
4561 files_struct *new_fsp = NULL;
4563 if (!VALID_STAT(*psbuf)) {
4564 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4567 if (total_data < 8) {
4568 return NT_STATUS_INVALID_PARAMETER;
4571 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4572 #ifdef LARGE_SMB_OFF_T
4573 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4574 #else /* LARGE_SMB_OFF_T */
4575 if (IVAL(pdata,4) != 0) {
4576 /* more than 32 bits? */
4577 return NT_STATUS_INVALID_PARAMETER;
4579 #endif /* LARGE_SMB_OFF_T */
4581 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4582 fname, (double)allocation_size ));
4584 if (allocation_size) {
4585 allocation_size = smb_roundup(conn, allocation_size);
4588 if(allocation_size == get_file_size(*psbuf)) {
4589 return NT_STATUS_OK;
4592 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4593 fname, (double)allocation_size ));
4595 if (fsp && fsp->fh->fd != -1) {
4596 /* Open file handle. */
4597 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4598 return map_nt_error_from_unix(errno);
4600 return NT_STATUS_OK;
4603 /* Pathname or stat or directory file. */
4605 status = open_file_ntcreate(conn, fname, psbuf,
4607 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4610 FILE_ATTRIBUTE_NORMAL,
4611 FORCE_OPLOCK_BREAK_TO_NONE,
4614 if (!NT_STATUS_IS_OK(status)) {
4615 /* NB. We check for open_was_deferred in the caller. */
4618 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4619 status = map_nt_error_from_unix(errno);
4620 close_file(new_fsp,NORMAL_CLOSE);
4624 close_file(new_fsp,NORMAL_CLOSE);
4625 return NT_STATUS_OK;
4628 /****************************************************************************
4629 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4630 ****************************************************************************/
4632 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4637 SMB_STRUCT_STAT *psbuf)
4641 if (total_data < 8) {
4642 return NT_STATUS_INVALID_PARAMETER;
4645 size = IVAL(pdata,0);
4646 #ifdef LARGE_SMB_OFF_T
4647 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4648 #else /* LARGE_SMB_OFF_T */
4649 if (IVAL(pdata,4) != 0) {
4650 /* more than 32 bits? */
4651 return NT_STATUS_INVALID_PARAMETER;
4653 #endif /* LARGE_SMB_OFF_T */
4654 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4655 "file %s to %.0f\n", fname, (double)size ));
4657 return smb_set_file_size(conn,
4664 /****************************************************************************
4665 Allow a UNIX info mknod.
4666 ****************************************************************************/
4668 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4672 SMB_STRUCT_STAT *psbuf)
4674 uint32 file_type = IVAL(pdata,56);
4675 #if defined(HAVE_MAKEDEV)
4676 uint32 dev_major = IVAL(pdata,60);
4677 uint32 dev_minor = IVAL(pdata,68);
4679 SMB_DEV_T dev = (SMB_DEV_T)0;
4680 uint32 raw_unixmode = IVAL(pdata,84);
4684 if (total_data < 100) {
4685 return NT_STATUS_INVALID_PARAMETER;
4688 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4689 if (!NT_STATUS_IS_OK(status)) {
4693 #if defined(HAVE_MAKEDEV)
4694 dev = makedev(dev_major, dev_minor);
4697 switch (file_type) {
4698 #if defined(S_IFIFO)
4699 case UNIX_TYPE_FIFO:
4700 unixmode |= S_IFIFO;
4703 #if defined(S_IFSOCK)
4704 case UNIX_TYPE_SOCKET:
4705 unixmode |= S_IFSOCK;
4708 #if defined(S_IFCHR)
4709 case UNIX_TYPE_CHARDEV:
4710 unixmode |= S_IFCHR;
4713 #if defined(S_IFBLK)
4714 case UNIX_TYPE_BLKDEV:
4715 unixmode |= S_IFBLK;
4719 return NT_STATUS_INVALID_PARAMETER;
4722 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4723 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4725 /* Ok - do the mknod. */
4726 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4727 return map_nt_error_from_unix(errno);
4730 /* If any of the other "set" calls fail we
4731 * don't want to end up with a half-constructed mknod.
4734 if (lp_inherit_perms(SNUM(conn))) {
4736 conn, parent_dirname(fname),
4740 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4741 status = map_nt_error_from_unix(errno);
4742 SMB_VFS_UNLINK(conn,fname);
4745 return NT_STATUS_OK;
4748 /****************************************************************************
4749 Deal with SMB_SET_FILE_UNIX_BASIC.
4750 ****************************************************************************/
4752 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4757 SMB_STRUCT_STAT *psbuf)
4759 struct timespec ts[2];
4760 uint32 raw_unixmode;
4763 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4764 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4765 NTSTATUS status = NT_STATUS_OK;
4766 BOOL delete_on_fail = False;
4767 enum perm_type ptype;
4769 if (total_data < 100) {
4770 return NT_STATUS_INVALID_PARAMETER;
4773 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4774 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4775 size=IVAL(pdata,0); /* first 8 Bytes are size */
4776 #ifdef LARGE_SMB_OFF_T
4777 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4778 #else /* LARGE_SMB_OFF_T */
4779 if (IVAL(pdata,4) != 0) {
4780 /* more than 32 bits? */
4781 return NT_STATUS_INVALID_PARAMETER;
4783 #endif /* LARGE_SMB_OFF_T */
4786 ts[0] = interpret_long_date(pdata+24); /* access_time */
4787 ts[1] = interpret_long_date(pdata+32); /* modification_time */
4788 set_owner = (uid_t)IVAL(pdata,40);
4789 set_grp = (gid_t)IVAL(pdata,48);
4790 raw_unixmode = IVAL(pdata,84);
4792 if (VALID_STAT(*psbuf)) {
4793 if (S_ISDIR(psbuf->st_mode)) {
4794 ptype = PERM_EXISTING_DIR;
4796 ptype = PERM_EXISTING_FILE;
4799 ptype = PERM_NEW_FILE;
4802 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
4803 if (!NT_STATUS_IS_OK(status)) {
4807 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
4808 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4809 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4811 if (!VALID_STAT(*psbuf)) {
4813 * The only valid use of this is to create character and block
4814 * devices, and named pipes. This is deprecated (IMHO) and
4815 * a new info level should be used for mknod. JRA.
4818 status = smb_unix_mknod(conn,
4823 if (!NT_STATUS_IS_OK(status)) {
4827 /* Ensure we don't try and change anything else. */
4828 raw_unixmode = SMB_MODE_NO_CHANGE;
4829 size = get_file_size(*psbuf);
4830 ts[0] = get_atimespec(psbuf);
4831 ts[1] = get_mtimespec(psbuf);
4833 * We continue here as we might want to change the
4836 delete_on_fail = True;
4840 /* Horrible backwards compatibility hack as an old server bug
4841 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4845 size = get_file_size(*psbuf);
4850 * Deal with the UNIX specific mode set.
4853 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4854 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4855 (unsigned int)unixmode, fname ));
4856 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
4857 return map_nt_error_from_unix(errno);
4862 * Deal with the UNIX specific uid set.
4865 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
4866 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4867 (unsigned int)set_owner, fname ));
4868 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
4869 status = map_nt_error_from_unix(errno);
4870 if (delete_on_fail) {
4871 SMB_VFS_UNLINK(conn,fname);
4878 * Deal with the UNIX specific gid set.
4881 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
4882 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4883 (unsigned int)set_owner, fname ));
4884 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
4885 status = map_nt_error_from_unix(errno);
4886 if (delete_on_fail) {
4887 SMB_VFS_UNLINK(conn,fname);
4893 /* Deal with any size changes. */
4895 status = smb_set_file_size(conn,
4900 if (!NT_STATUS_IS_OK(status)) {
4904 /* Deal with any time changes. */
4906 return smb_set_file_time(conn,
4913 /****************************************************************************
4914 Create a directory with POSIX semantics.
4915 ****************************************************************************/
4917 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
4921 SMB_STRUCT_STAT *psbuf,
4922 int *pdata_return_size)
4924 NTSTATUS status = NT_STATUS_OK;
4925 uint32 raw_unixmode = 0;
4926 uint32 mod_unixmode = 0;
4927 mode_t unixmode = (mode_t)0;
4928 files_struct *fsp = NULL;
4929 uint16 info_level_return = 0;
4930 char *pdata = *ppdata;
4932 if (total_data < 10) {
4933 return NT_STATUS_INVALID_PARAMETER;
4936 raw_unixmode = IVAL(pdata,8);
4937 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
4938 if (!NT_STATUS_IS_OK(status)) {
4942 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
4944 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
4945 fname, (unsigned int)unixmode ));
4947 status = open_directory(conn,
4950 FILE_READ_ATTRIBUTES, /* Just a stat open */
4951 FILE_SHARE_NONE, /* Ignored for stat opens */
4958 if (NT_STATUS_IS_OK(status)) {
4959 close_file(fsp, NORMAL_CLOSE);
4962 info_level_return = SVAL(pdata,12);
4964 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
4965 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
4967 *pdata_return_size = 8;
4970 /* Realloc the data size */
4971 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
4972 if (*ppdata == NULL) {
4973 *pdata_return_size = 0;
4974 return NT_STATUS_NO_MEMORY;
4977 SSVAL(pdata,0,NO_OPLOCK_RETURN);
4980 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
4981 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
4982 SSVAL(pdata,6,0); /* Padding. */
4983 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
4985 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
4986 SSVAL(pdata,6,0); /* Padding. */
4992 /****************************************************************************
4993 Open/Create a file with POSIX semantics.
4994 ****************************************************************************/
4996 static NTSTATUS smb_posix_open(connection_struct *conn,
5000 SMB_STRUCT_STAT *psbuf,
5001 int *pdata_return_size)
5003 BOOL extended_oplock_granted = False;
5004 char *pdata = *ppdata;
5006 uint32 wire_open_mode = 0;
5007 uint32 raw_unixmode = 0;
5008 uint32 mod_unixmode = 0;
5009 uint32 create_disp = 0;
5010 uint32 access_mask = 0;
5011 uint32 create_options = 0;
5012 NTSTATUS status = NT_STATUS_OK;
5013 mode_t unixmode = (mode_t)0;
5014 files_struct *fsp = NULL;
5015 int oplock_request = 0;
5017 uint16 info_level_return = 0;
5019 if (total_data < 14) {
5020 return NT_STATUS_INVALID_PARAMETER;
5023 flags = IVAL(pdata,0);
5024 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5025 if (oplock_request) {
5026 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5029 wire_open_mode = IVAL(pdata,4);
5031 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5032 return smb_posix_mkdir(conn,
5040 switch (wire_open_mode & SMB_ACCMODE) {
5042 access_mask = FILE_READ_DATA;
5045 access_mask = FILE_WRITE_DATA;
5048 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5051 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5052 (unsigned int)wire_open_mode ));
5053 return NT_STATUS_INVALID_PARAMETER;
5056 wire_open_mode &= ~SMB_ACCMODE;
5058 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5059 create_disp = FILE_CREATE;
5060 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5061 create_disp = FILE_OVERWRITE_IF;
5062 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5063 create_disp = FILE_OPEN_IF;
5065 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5066 (unsigned int)wire_open_mode ));
5067 return NT_STATUS_INVALID_PARAMETER;
5070 raw_unixmode = IVAL(pdata,8);
5071 status = unix_perms_from_wire(conn,
5074 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5077 if (!NT_STATUS_IS_OK(status)) {
5081 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5083 if (wire_open_mode & SMB_O_SYNC) {
5084 create_options |= FILE_WRITE_THROUGH;
5086 if (wire_open_mode & SMB_O_APPEND) {
5087 access_mask |= FILE_APPEND_DATA;
5089 if (wire_open_mode & SMB_O_DIRECT) {
5090 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5093 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5095 (unsigned int)wire_open_mode,
5096 (unsigned int)unixmode ));
5098 status = open_file_ntcreate(conn,
5102 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5104 0, /* no create options yet. */
5110 if (!NT_STATUS_IS_OK(status)) {
5114 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5115 extended_oplock_granted = True;
5118 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5119 extended_oplock_granted = True;
5122 info_level_return = SVAL(pdata,12);
5124 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5125 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
5127 *pdata_return_size = 8;
5130 /* Realloc the data size */
5131 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5132 if (*ppdata == NULL) {
5133 close_file(fsp,ERROR_CLOSE);
5134 *pdata_return_size = 0;
5135 return NT_STATUS_NO_MEMORY;
5138 if (extended_oplock_granted) {
5139 if (flags & REQUEST_BATCH_OPLOCK) {
5140 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5142 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5144 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5145 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5147 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5150 SSVAL(pdata,2,fsp->fnum);
5151 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5152 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
5153 SSVAL(pdata,6,0); /* padding. */
5154 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
5156 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
5157 SSVAL(pdata,6,0); /* padding. */
5159 return NT_STATUS_OK;
5162 /****************************************************************************
5163 Delete a file with POSIX semantics.
5164 ****************************************************************************/
5166 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5170 SMB_STRUCT_STAT *psbuf)
5172 NTSTATUS status = NT_STATUS_OK;
5173 files_struct *fsp = NULL;
5177 if (total_data < 2) {
5178 return NT_STATUS_INVALID_PARAMETER;
5181 flags = SVAL(pdata,0);
5183 if (!VALID_STAT(*psbuf)) {
5184 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5187 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5188 !VALID_STAT_OF_DIR(*psbuf)) {
5189 return NT_STATUS_NOT_A_DIRECTORY;
5192 DEBUG(10,("smb_posix_unlink: %s %s\n",
5193 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5196 if (VALID_STAT_OF_DIR(*psbuf)) {
5197 status = open_directory(conn,
5201 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5203 FILE_DELETE_ON_CLOSE,
5204 FILE_FLAG_POSIX_SEMANTICS|0777,
5210 status = open_file_ntcreate(conn,
5214 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5217 FILE_FLAG_POSIX_SEMANTICS|0777,
5218 0, /* No oplock, but break existing ones. */
5222 * For file opens we must set the delete on close
5226 if (!NT_STATUS_IS_OK(status)) {
5230 status = smb_set_file_disposition_info(conn,
5238 if (!NT_STATUS_IS_OK(status)) {
5241 return close_file(fsp, NORMAL_CLOSE);
5244 /****************************************************************************
5245 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5246 ****************************************************************************/
5248 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5249 unsigned int tran_call,
5250 char **pparams, int total_params, char **ppdata, int total_data,
5251 unsigned int max_data_bytes)
5253 char *params = *pparams;
5254 char *pdata = *ppdata;
5256 SMB_STRUCT_STAT sbuf;
5258 files_struct *fsp = NULL;
5259 NTSTATUS status = NT_STATUS_OK;
5260 int data_return_size = 0;
5263 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5268 if (tran_call == TRANSACT2_SETFILEINFO) {
5269 if (total_params < 4) {
5270 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5273 fsp = file_fsp(params,0);
5274 info_level = SVAL(params,2);
5276 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5278 * This is actually a SETFILEINFO on a directory
5279 * handle (returned from an NT SMB). NT5.0 seems
5280 * to do this call. JRA.
5282 pstrcpy(fname, fsp->fsp_name);
5283 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5284 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5285 return UNIXERROR(ERRDOS,ERRbadpath);
5287 } else if (fsp && fsp->print_file) {
5289 * Doing a DELETE_ON_CLOSE should cancel a print job.
5291 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5292 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5294 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5297 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5300 return (UNIXERROR(ERRDOS,ERRbadpath));
5303 * Original code - this is an open file.
5305 CHECK_FSP(fsp,conn);
5307 pstrcpy(fname, fsp->fsp_name);
5309 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5310 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5311 return(UNIXERROR(ERRDOS,ERRbadfid));
5316 if (total_params < 7) {
5317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5320 info_level = SVAL(params,0);
5321 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5322 if (!NT_STATUS_IS_OK(status)) {
5323 return ERROR_NT(status);
5326 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
5328 status = unix_convert(conn, fname, False, NULL, &sbuf);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 return ERROR_NT(status);
5333 status = check_name(conn, fname);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 return ERROR_NT(status);
5339 * For CIFS UNIX extensions the target name may not exist.
5342 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5343 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5344 return UNIXERROR(ERRDOS,ERRbadpath);
5348 if (!CAN_WRITE(conn)) {
5349 return ERROR_DOS(ERRSRV,ERRaccess);
5352 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5353 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5356 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5357 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5359 /* Realloc the parameter size */
5360 *pparams = (char *)SMB_REALLOC(*pparams,2);
5361 if (*pparams == NULL) {
5362 return ERROR_NT(NT_STATUS_NO_MEMORY);
5368 if (fsp && !null_timespec(fsp->pending_modtime)) {
5369 /* the pending modtime overrides the current modtime */
5370 set_mtimespec(&sbuf, fsp->pending_modtime);
5373 switch (info_level) {
5375 case SMB_INFO_STANDARD:
5377 status = smb_set_info_standard(conn,
5386 case SMB_INFO_SET_EA:
5388 status = smb_info_set_ea(conn,
5396 case SMB_SET_FILE_BASIC_INFO:
5397 case SMB_FILE_BASIC_INFORMATION:
5399 status = smb_set_file_basic_info(conn,
5408 case SMB_FILE_ALLOCATION_INFORMATION:
5409 case SMB_SET_FILE_ALLOCATION_INFO:
5411 status = smb_set_file_allocation_info(conn,
5420 case SMB_FILE_END_OF_FILE_INFORMATION:
5421 case SMB_SET_FILE_END_OF_FILE_INFO:
5423 status = smb_set_file_end_of_file_info(conn,
5432 case SMB_FILE_DISPOSITION_INFORMATION:
5433 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5436 /* JRA - We used to just ignore this on a path ?
5437 * Shouldn't this be invalid level on a pathname
5440 if (tran_call != TRANSACT2_SETFILEINFO) {
5441 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5444 status = smb_set_file_disposition_info(conn,
5453 case SMB_FILE_POSITION_INFORMATION:
5455 status = smb_file_position_information(conn,
5462 /* From tridge Samba4 :
5463 * MODE_INFORMATION in setfileinfo (I have no
5464 * idea what "mode information" on a file is - it takes a value of 0,
5465 * 2, 4 or 6. What could it be?).
5468 case SMB_FILE_MODE_INFORMATION:
5470 status = smb_file_mode_information(conn,
5477 * CIFS UNIX extensions.
5480 case SMB_SET_FILE_UNIX_BASIC:
5482 status = smb_set_file_unix_basic(conn,
5491 case SMB_SET_FILE_UNIX_LINK:
5493 if (tran_call != TRANSACT2_SETPATHINFO) {
5494 /* We must have a pathname for this. */
5495 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5497 status = smb_set_file_unix_link(conn,
5505 case SMB_SET_FILE_UNIX_HLINK:
5507 if (tran_call != TRANSACT2_SETPATHINFO) {
5508 /* We must have a pathname for this. */
5509 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5511 status = smb_set_file_unix_hlink(conn,
5520 case SMB_FILE_RENAME_INFORMATION:
5522 status = smb_file_rename_information(conn,
5532 #if defined(HAVE_POSIX_ACLS)
5533 case SMB_SET_POSIX_ACL:
5535 status = smb_set_posix_acl(conn,
5545 case SMB_SET_POSIX_LOCK:
5547 if (tran_call != TRANSACT2_SETFILEINFO) {
5548 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5550 status = smb_set_posix_lock(conn,
5559 case SMB_POSIX_PATH_OPEN:
5561 if (tran_call != TRANSACT2_SETPATHINFO) {
5562 /* We must have a pathname for this. */
5563 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5566 status = smb_posix_open(conn,
5575 case SMB_POSIX_PATH_UNLINK:
5577 if (tran_call != TRANSACT2_SETPATHINFO) {
5578 /* We must have a pathname for this. */
5579 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5582 status = smb_posix_unlink(conn,
5591 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5595 if (!NT_STATUS_IS_OK(status)) {
5596 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5597 /* We have re-scheduled this call. */
5600 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5601 /* We have re-scheduled this call. */
5604 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5605 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5607 return ERROR_NT(status);
5611 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5616 /****************************************************************************
5617 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5618 ****************************************************************************/
5620 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5621 char **pparams, int total_params, char **ppdata, int total_data,
5622 unsigned int max_data_bytes)
5624 char *params = *pparams;
5625 char *pdata = *ppdata;
5627 SMB_STRUCT_STAT sbuf;
5628 NTSTATUS status = NT_STATUS_OK;
5629 struct ea_list *ea_list = NULL;
5631 if (!CAN_WRITE(conn))
5632 return ERROR_DOS(ERRSRV,ERRaccess);
5634 if (total_params < 5) {
5635 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5638 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5639 if (!NT_STATUS_IS_OK(status)) {
5640 return ERROR_NT(status);
5643 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5645 status = unix_convert(conn, directory, False, NULL, &sbuf);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 return ERROR_NT(status);
5650 status = check_name(conn, directory);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5653 return ERROR_NT(status);
5656 /* Any data in this call is an EA list. */
5657 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5658 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5662 * OS/2 workplace shell seems to send SET_EA requests of "null"
5663 * length (4 bytes containing IVAL 4).
5664 * They seem to have no effect. Bug #3212. JRA.
5667 if (total_data != 4) {
5668 if (total_data < 10) {
5669 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5672 if (IVAL(pdata,0) > total_data) {
5673 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5674 IVAL(pdata,0), (unsigned int)total_data));
5675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5678 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5681 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5683 } else if (IVAL(pdata,0) != 4) {
5684 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5687 status = create_directory(conn, directory);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 return ERROR_NT(status);
5693 /* Try and set any given EA. */
5695 status = set_ea(conn, NULL, directory, ea_list);
5696 if (!NT_STATUS_IS_OK(status)) {
5697 return ERROR_NT(status);
5701 /* Realloc the parameter and data sizes */
5702 *pparams = (char *)SMB_REALLOC(*pparams,2);
5703 if(*pparams == NULL) {
5704 return ERROR_NT(NT_STATUS_NO_MEMORY);
5710 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5715 /****************************************************************************
5716 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5717 We don't actually do this - we just send a null response.
5718 ****************************************************************************/
5720 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5721 char **pparams, int total_params, char **ppdata, int total_data,
5722 unsigned int max_data_bytes)
5724 static uint16 fnf_handle = 257;
5725 char *params = *pparams;
5728 if (total_params < 6) {
5729 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5732 info_level = SVAL(params,4);
5733 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5735 switch (info_level) {
5740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5743 /* Realloc the parameter and data sizes */
5744 *pparams = (char *)SMB_REALLOC(*pparams,6);
5745 if (*pparams == NULL) {
5746 return ERROR_NT(NT_STATUS_NO_MEMORY);
5750 SSVAL(params,0,fnf_handle);
5751 SSVAL(params,2,0); /* No changes */
5752 SSVAL(params,4,0); /* No EA errors */
5759 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5764 /****************************************************************************
5765 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5766 changes). Currently this does nothing.
5767 ****************************************************************************/
5769 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5770 char **pparams, int total_params, char **ppdata, int total_data,
5771 unsigned int max_data_bytes)
5773 char *params = *pparams;
5775 DEBUG(3,("call_trans2findnotifynext\n"));
5777 /* Realloc the parameter and data sizes */
5778 *pparams = (char *)SMB_REALLOC(*pparams,4);
5779 if (*pparams == NULL) {
5780 return ERROR_NT(NT_STATUS_NO_MEMORY);
5784 SSVAL(params,0,0); /* No changes */
5785 SSVAL(params,2,0); /* No EA errors */
5787 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5792 /****************************************************************************
5793 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5794 ****************************************************************************/
5796 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5797 char **pparams, int total_params, char **ppdata, int total_data,
5798 unsigned int max_data_bytes)
5800 char *params = *pparams;
5803 int max_referral_level;
5805 DEBUG(10,("call_trans2getdfsreferral\n"));
5807 if (total_params < 3) {
5808 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5811 max_referral_level = SVAL(params,0);
5813 if(!lp_host_msdfs())
5814 return ERROR_DOS(ERRDOS,ERRbadfunc);
5816 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5817 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5818 return UNIXERROR(ERRDOS,ERRbadfile);
5820 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5821 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5826 #define LMCAT_SPL 0x53
5827 #define LMFUNC_GETJOBID 0x60
5829 /****************************************************************************
5830 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5831 ****************************************************************************/
5833 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5834 char **pparams, int total_params, char **ppdata, int total_data,
5835 unsigned int max_data_bytes)
5837 char *pdata = *ppdata;
5838 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5840 /* check for an invalid fid before proceeding */
5843 return(ERROR_DOS(ERRDOS,ERRbadfid));
5845 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5846 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5847 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5848 if (*ppdata == NULL) {
5849 return ERROR_NT(NT_STATUS_NO_MEMORY);
5853 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5854 CAN ACCEPT THIS IN UNICODE. JRA. */
5856 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
5857 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5858 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5859 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5862 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5863 return ERROR_DOS(ERRSRV,ERRerror);
5867 /****************************************************************************
5868 Reply to a SMBfindclose (stop trans2 directory search).
5869 ****************************************************************************/
5871 int reply_findclose(connection_struct *conn,
5872 char *inbuf,char *outbuf,int length,int bufsize)
5875 int dptr_num=SVALS(inbuf,smb_vwv0);
5876 START_PROFILE(SMBfindclose);
5878 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5880 dptr_close(&dptr_num);
5882 outsize = set_message(outbuf,0,0,False);
5884 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5886 END_PROFILE(SMBfindclose);
5890 /****************************************************************************
5891 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5892 ****************************************************************************/
5894 int reply_findnclose(connection_struct *conn,
5895 char *inbuf,char *outbuf,int length,int bufsize)
5899 START_PROFILE(SMBfindnclose);
5901 dptr_num = SVAL(inbuf,smb_vwv0);
5903 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5905 /* We never give out valid handles for a
5906 findnotifyfirst - so any dptr_num is ok here.
5909 outsize = set_message(outbuf,0,0,False);
5911 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5913 END_PROFILE(SMBfindnclose);
5917 int handle_trans2(connection_struct *conn,
5918 struct trans_state *state,
5919 char *inbuf, char *outbuf, int size, int bufsize)
5923 if (Protocol >= PROTOCOL_NT1) {
5924 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5927 /* Now we must call the relevant TRANS2 function */
5928 switch(state->call) {
5929 case TRANSACT2_OPEN:
5931 START_PROFILE(Trans2_open);
5932 outsize = call_trans2open(
5933 conn, inbuf, outbuf, bufsize,
5934 &state->param, state->total_param,
5935 &state->data, state->total_data,
5936 state->max_data_return);
5937 END_PROFILE(Trans2_open);
5941 case TRANSACT2_FINDFIRST:
5943 START_PROFILE(Trans2_findfirst);
5944 outsize = call_trans2findfirst(
5945 conn, inbuf, outbuf, bufsize,
5946 &state->param, state->total_param,
5947 &state->data, state->total_data,
5948 state->max_data_return);
5949 END_PROFILE(Trans2_findfirst);
5953 case TRANSACT2_FINDNEXT:
5955 START_PROFILE(Trans2_findnext);
5956 outsize = call_trans2findnext(
5957 conn, inbuf, outbuf, size, bufsize,
5958 &state->param, state->total_param,
5959 &state->data, state->total_data,
5960 state->max_data_return);
5961 END_PROFILE(Trans2_findnext);
5965 case TRANSACT2_QFSINFO:
5967 START_PROFILE(Trans2_qfsinfo);
5968 outsize = call_trans2qfsinfo(
5969 conn, inbuf, outbuf, size, bufsize,
5970 &state->param, state->total_param,
5971 &state->data, state->total_data,
5972 state->max_data_return);
5973 END_PROFILE(Trans2_qfsinfo);
5977 case TRANSACT2_SETFSINFO:
5979 START_PROFILE(Trans2_setfsinfo);
5980 outsize = call_trans2setfsinfo(
5981 conn, inbuf, outbuf, size, bufsize,
5982 &state->param, state->total_param,
5983 &state->data, state->total_data,
5984 state->max_data_return);
5985 END_PROFILE(Trans2_setfsinfo);
5989 case TRANSACT2_QPATHINFO:
5990 case TRANSACT2_QFILEINFO:
5992 START_PROFILE(Trans2_qpathinfo);
5993 outsize = call_trans2qfilepathinfo(
5994 conn, inbuf, outbuf, size, bufsize, state->call,
5995 &state->param, state->total_param,
5996 &state->data, state->total_data,
5997 state->max_data_return);
5998 END_PROFILE(Trans2_qpathinfo);
6002 case TRANSACT2_SETPATHINFO:
6003 case TRANSACT2_SETFILEINFO:
6005 START_PROFILE(Trans2_setpathinfo);
6006 outsize = call_trans2setfilepathinfo(
6007 conn, inbuf, outbuf, size, bufsize, state->call,
6008 &state->param, state->total_param,
6009 &state->data, state->total_data,
6010 state->max_data_return);
6011 END_PROFILE(Trans2_setpathinfo);
6015 case TRANSACT2_FINDNOTIFYFIRST:
6017 START_PROFILE(Trans2_findnotifyfirst);
6018 outsize = call_trans2findnotifyfirst(
6019 conn, inbuf, outbuf, size, bufsize,
6020 &state->param, state->total_param,
6021 &state->data, state->total_data,
6022 state->max_data_return);
6023 END_PROFILE(Trans2_findnotifyfirst);
6027 case TRANSACT2_FINDNOTIFYNEXT:
6029 START_PROFILE(Trans2_findnotifynext);
6030 outsize = call_trans2findnotifynext(
6031 conn, inbuf, outbuf, size, bufsize,
6032 &state->param, state->total_param,
6033 &state->data, state->total_data,
6034 state->max_data_return);
6035 END_PROFILE(Trans2_findnotifynext);
6039 case TRANSACT2_MKDIR:
6041 START_PROFILE(Trans2_mkdir);
6042 outsize = call_trans2mkdir(
6043 conn, inbuf, outbuf, size, bufsize,
6044 &state->param, state->total_param,
6045 &state->data, state->total_data,
6046 state->max_data_return);
6047 END_PROFILE(Trans2_mkdir);
6051 case TRANSACT2_GET_DFS_REFERRAL:
6053 START_PROFILE(Trans2_get_dfs_referral);
6054 outsize = call_trans2getdfsreferral(
6055 conn, inbuf, outbuf, size, bufsize,
6056 &state->param, state->total_param,
6057 &state->data, state->total_data,
6058 state->max_data_return);
6059 END_PROFILE(Trans2_get_dfs_referral);
6063 case TRANSACT2_IOCTL:
6065 START_PROFILE(Trans2_ioctl);
6066 outsize = call_trans2ioctl(
6067 conn, inbuf, outbuf, size, bufsize,
6068 &state->param, state->total_param,
6069 &state->data, state->total_data,
6070 state->max_data_return);
6071 END_PROFILE(Trans2_ioctl);
6076 /* Error in request */
6077 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6078 outsize = ERROR_DOS(ERRSRV,ERRerror);
6084 /****************************************************************************
6085 Reply to a SMBtrans2.
6086 ****************************************************************************/
6088 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6089 int size, int bufsize)
6092 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6093 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6094 unsigned int psoff = SVAL(inbuf, smb_psoff);
6095 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6096 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6097 struct trans_state *state;
6100 START_PROFILE(SMBtrans2);
6102 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6103 if (!NT_STATUS_IS_OK(result)) {
6104 DEBUG(2, ("Got invalid trans2 request: %s\n",
6105 nt_errstr(result)));
6106 END_PROFILE(SMBtrans2);
6107 return ERROR_NT(result);
6110 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6111 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6112 END_PROFILE(SMBtrans2);
6113 return ERROR_DOS(ERRSRV,ERRaccess);
6116 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6117 DEBUG(0, ("talloc failed\n"));
6118 END_PROFILE(SMBtrans2);
6119 return ERROR_NT(NT_STATUS_NO_MEMORY);
6122 state->cmd = SMBtrans2;
6124 state->mid = SVAL(inbuf, smb_mid);
6125 state->vuid = SVAL(inbuf, smb_uid);
6126 state->setup_count = SVAL(inbuf, smb_suwcnt);
6127 state->setup = NULL;
6128 state->total_param = SVAL(inbuf, smb_tpscnt);
6129 state->param = NULL;
6130 state->total_data = SVAL(inbuf, smb_tdscnt);
6132 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6133 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6134 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6135 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6136 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6138 state->call = tran_call;
6140 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6141 is so as a sanity check */
6142 if (state->setup_count != 1) {
6144 * Need to have rc=0 for ioctl to get job id for OS/2.
6145 * Network printing will fail if function is not successful.
6146 * Similar function in reply.c will be used if protocol
6147 * is LANMAN1.0 instead of LM1.2X002.
6148 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6149 * outbuf doesn't have to be set(only job id is used).
6151 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6152 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6153 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6154 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6156 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6157 DEBUG(2,("Transaction is %d\n",tran_call));
6159 END_PROFILE(SMBtrans2);
6160 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6164 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6167 if (state->total_data) {
6168 /* Can't use talloc here, the core routines do realloc on the
6169 * params and data. */
6170 state->data = (char *)SMB_MALLOC(state->total_data);
6171 if (state->data == NULL) {
6172 DEBUG(0,("reply_trans2: data malloc fail for %u "
6173 "bytes !\n", (unsigned int)state->total_data));
6175 END_PROFILE(SMBtrans2);
6176 return(ERROR_DOS(ERRDOS,ERRnomem));
6178 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6180 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6181 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6184 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6187 if (state->total_param) {
6188 /* Can't use talloc here, the core routines do realloc on the
6189 * params and data. */
6190 state->param = (char *)SMB_MALLOC(state->total_param);
6191 if (state->param == NULL) {
6192 DEBUG(0,("reply_trans: param malloc fail for %u "
6193 "bytes !\n", (unsigned int)state->total_param));
6194 SAFE_FREE(state->data);
6196 END_PROFILE(SMBtrans2);
6197 return(ERROR_DOS(ERRDOS,ERRnomem));
6199 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6201 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6202 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6205 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6208 state->received_data = dscnt;
6209 state->received_param = pscnt;
6211 if ((state->received_param == state->total_param) &&
6212 (state->received_data == state->total_data)) {
6214 outsize = handle_trans2(conn, state, inbuf, outbuf,
6216 SAFE_FREE(state->data);
6217 SAFE_FREE(state->param);
6219 END_PROFILE(SMBtrans2);
6223 DLIST_ADD(conn->pending_trans, state);
6225 /* We need to send an interim response then receive the rest
6226 of the parameter/data bytes */
6227 outsize = set_message(outbuf,0,0,False);
6229 END_PROFILE(SMBtrans2);
6234 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6235 SAFE_FREE(state->data);
6236 SAFE_FREE(state->param);
6238 END_PROFILE(SMBtrans2);
6239 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6243 /****************************************************************************
6244 Reply to a SMBtranss2
6245 ****************************************************************************/
6247 int reply_transs2(connection_struct *conn,
6248 char *inbuf,char *outbuf,int size,int bufsize)
6251 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6252 struct trans_state *state;
6254 START_PROFILE(SMBtranss2);
6258 for (state = conn->pending_trans; state != NULL;
6259 state = state->next) {
6260 if (state->mid == SVAL(inbuf,smb_mid)) {
6265 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6266 END_PROFILE(SMBtranss2);
6267 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6270 /* Revise state->total_param and state->total_data in case they have
6271 changed downwards */
6273 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6274 state->total_param = SVAL(inbuf, smb_tpscnt);
6275 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6276 state->total_data = SVAL(inbuf, smb_tdscnt);
6278 pcnt = SVAL(inbuf, smb_spscnt);
6279 poff = SVAL(inbuf, smb_spsoff);
6280 pdisp = SVAL(inbuf, smb_spsdisp);
6282 dcnt = SVAL(inbuf, smb_sdscnt);
6283 doff = SVAL(inbuf, smb_sdsoff);
6284 ddisp = SVAL(inbuf, smb_sdsdisp);
6286 state->received_param += pcnt;
6287 state->received_data += dcnt;
6289 if ((state->received_data > state->total_data) ||
6290 (state->received_param > state->total_param))
6294 if (pdisp+pcnt > state->total_param)
6296 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6298 if (pdisp > state->total_param)
6300 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6301 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6303 if (state->param + pdisp < state->param)
6306 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6311 if (ddisp+dcnt > state->total_data)
6313 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6315 if (ddisp > state->total_data)
6317 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6318 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6320 if (state->data + ddisp < state->data)
6323 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6327 if ((state->received_param < state->total_param) ||
6328 (state->received_data < state->total_data)) {
6329 END_PROFILE(SMBtranss2);
6333 /* construct_reply_common has done us the favor to pre-fill the
6334 * command field with SMBtranss2 which is wrong :-)
6336 SCVAL(outbuf,smb_com,SMBtrans2);
6338 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6340 DLIST_REMOVE(conn->pending_trans, state);
6341 SAFE_FREE(state->data);
6342 SAFE_FREE(state->param);
6346 END_PROFILE(SMBtranss2);
6347 return(ERROR_DOS(ERRSRV,ERRnosupport));
6350 END_PROFILE(SMBtranss2);
6355 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6356 DLIST_REMOVE(conn->pending_trans, state);
6357 SAFE_FREE(state->data);
6358 SAFE_FREE(state->param);
6360 END_PROFILE(SMBtranss2);
6361 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);