smb_query_fileinfo.c revision f96bd5c800e73e351b0b6e4bd7f00b578dad29bb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_vops.h>
#include <smbsrv/smb_fsops.h>
/*
*
* SMB_INFO_STANDARD
* SMB_INFO_QUERY_EA_SIZE
* SMB_INFO_QUERY_EAS_FROM_LIST
* SMB_INFO_QUERY_ALL_EAS - not valid for pipes
* SMB_INFO_IS_NAME_VALID - only valid when query is by path
*
* SMB_QUERY_FILE_BASIC_INFO
* SMB_QUERY_FILE_STANDARD_INFO
* SMB_QUERY_FILE_EA_INFO
* SMB_QUERY_FILE_NAME_INFO
* SMB_QUERY_FILE_ALL_INFO
* SMB_QUERY_FILE_ALT_NAME_INFO - not valid for pipes
* SMB_QUERY_FILE_STREAM_INFO - not valid for pipes
* SMB_QUERY_FILE_COMPRESSION_INFO - not valid for pipes
*
* Supported Passthrough levels:
* SMB_FILE_BASIC_INFORMATION
* SMB_FILE_STANDARD_INFORMATION
* SMB_FILE_INTERNAL_INFORMATION
* SMB_FILE_EA_INFORMATION
* SMB_FILE_ACCESS_INFORMATION - not yet supported quen query by path
* SMB_FILE_NAME_INFORMATION
* SMB_FILE_ALL_INFORMATION
* SMB_FILE_ALT_NAME_INFORMATION - not valid for pipes
* SMB_FILE_STREAM_INFORMATION - not valid for pipes
* SMB_FILE_COMPRESSION_INFORMATION - not valid for pipes
* SMB_FILE_ATTR_TAG_INFORMATION - not valid for pipes
*
* Internal levels representing non trans2 requests
* SMB_QUERY_INFORMATION
* SMB_QUERY_INFORMATION2
*/
typedef struct smb_queryinfo {
char qi_name83[SMB_SHORTNAMELEN];
char qi_shortname[SMB_SHORTNAMELEN];
char qi_name[MAXPATHLEN];
uint16_t, char *);
uint16_t, smb_queryinfo_t *);
uint16_t, smb_queryinfo_t *);
uint16_t, smb_queryinfo_t *);
smb_queryinfo_t *);
char *, size_t);
/*
* smb_com_trans2_query_file_information
*/
{
return (SDRC_ERROR);
return (SDRC_ERROR);
return (SDRC_SUCCESS);
}
/*
* smb_com_trans2_query_path_information
*/
{
char *path;
return (SDRC_ERROR);
}
return (SDRC_ERROR);
return (SDRC_ERROR);
return (SDRC_SUCCESS);
}
/*
* smb_com_query_information (aka getattr)
*/
{
int rc;
}
void
{
}
{
return (SDRC_ERROR);
}
return (SDRC_ERROR);
return (SDRC_SUCCESS);
}
/*
* smb_com_query_information2 (aka getattre)
*/
{
int rc;
}
void
{
}
{
return (SDRC_ERROR);
return (SDRC_SUCCESS);
}
/*
* smb_query_by_fid
*
* Common code for querying file information by open file (or pipe) id.
* Use the id to identify the node / pipe object and request the
* smb_queryinfo_t data for that object.
*/
static int
{
int rc;
return (-1);
}
if (infolev == SMB_INFO_IS_NAME_VALID) {
return (-1);
}
return (-1);
}
case SMB_FTYPE_DISK:
break;
case SMB_FTYPE_MESG_PIPE:
break;
default:
rc = -1;
break;
}
if (rc == 0)
return (rc);
}
/*
* smb_query_by_path
*
* Common code for querying file information by file name.
* Use the file name to identify the node object and request the
* smb_queryinfo_t data for that node.
*
* Querying attributes on a named pipe by name is an error and
* is handled in the calling functions so that they can return
* the appropriate error status code (which differs by caller).
*/
static int
{
int rc;
int len;
/* VALID, but not yet supported */
if (infolev == SMB_FILE_ACCESS_INFORMATION) {
return (-1);
}
/*
* Some MS clients pass NULL file names. NT interprets this as "\".
* Otherwise, if path is not "\\", remove the terminating slash.
*/
path = "\\";
else {
}
}
if (rc == 0) {
}
if (rc != 0) {
else
return (-1);
}
if (rc != 0) {
return (rc);
}
/* If delete_on_close - NT_STATUS_DELETE_PENDING */
if (qinfo->qi_delete_on_close) {
return (-1);
}
return (rc);
}
/*
* smb_size32
* Some responses only support 32 bit file sizes. If the file size
* exceeds UINT_MAX (32 bit) we return UINT_MAX in the response.
*/
static uint32_t
{
}
/*
* smb_query_encode_response
*
* Encode the data from smb_queryinfo_t into client response
*/
int
{
switch (infolev) {
case SMB_QUERY_INFORMATION:
10,
0);
break;
case SMB_QUERY_INFORMATION2:
11,
break;
break;
case SMB_INFO_STANDARD:
"YYYllw" : "yyyllw"),
break;
case SMB_INFO_QUERY_EA_SIZE:
"YYYllwl" : "yyyllwl"),
break;
case SMB_INFO_QUERY_ALL_EAS:
break;
case SMB_INFO_IS_NAME_VALID:
break;
/*
* NT includes 6 bytes (spec says 4) at the end of this
* response, which are required by NetBench 5.01.
*/
dattr);
break;
/* 2-byte pad at end */
break;
case SMB_QUERY_FILE_EA_INFO:
case SMB_FILE_EA_INFORMATION:
break;
case SMB_QUERY_FILE_NAME_INFO:
break;
case SMB_QUERY_FILE_ALL_INFO:
case SMB_FILE_ALL_INFORMATION:
/*
* There is a 6-byte pad between Attributes and AllocationSize,
* and a 2-byte pad after the Directory field.
*/
0);
break;
break;
break;
datasz, 0, 0, 0, 0);
break;
break;
/*
* If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the
* second dword should be the reparse tag. Otherwise
* the tag value should be set to zero.
* We don't support reparse points, so we set the tag
* to zero.
*/
break;
default:
return (-1);
}
return (0);
}
/*
* smb_encode_stream_info
*
* This function encodes the streams information.
* The following rules about how have been derived from observed NT
* behaviour.
*
* If the target is a file:
* 1. If there are no named streams, the response should still contain
* an entry for the unnamed stream.
* 2. If there are named streams, the response should contain an entry
* for the unnamed stream followed by the entries for the named
* streams.
*
* If the target is a directory:
* 1. If there are no streams, the response is complete. Directories
* do not report the unnamed stream.
* 2. If there are streams, the response should contain entries for
* those streams but there should not be an entry for the unnamed
* stream.
*
* Note that the stream name lengths exclude the null terminator but
* the field lengths (i.e. next offset calculations) need to include
* the null terminator and be padded to a multiple of 8 bytes. The
* last entry does not seem to need any padding.
*
* If an error is encountered when trying to read the stream entries
* (smb_odir_read_streaminfo) it is treated as if there are no [more]
* entries. The entries that have been read so far are returned and
* no error is reported.
*
* Offset calculation:
* 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24
*/
static void
{
char *stream_name;
int rc = 0;
if (SMB_IS_STREAM(fnode)) {
}
if (odid != 0)
/* If not a directory, encode an entry for the unnamed stream. */
if (!is_dir) {
stream_name = "::$DATA";
if (done)
next_offset = 0;
else
}
/*
* Since last packet does not have a pad we need to check
* for the next stream before we encode the current one
*/
while (!done) {
sinfo_next->si_name[0] = 0;
next_offset = 0;
pad = 0;
} else {
next_offset += pad;
}
}
if (od) {
}
}
/*
* smb_pad_align
*
* Returns the number of bytes required to pad an offset to the
* specified alignment.
*/
{
if (pad != 0)
return (pad);
}
/*
* smb_query_pathname
*
* Determine the absolute pathname of 'node' within the share.
* For some levels (e.g. ALL_INFO) the pathname should include the
* sharename for others (e.g. NAME_INFO) the pathname should be
* relative to the share.
* For example if the node represents file "test1.txt" in directory
* "dir1" on share "share1"
* - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt
* - if include_share is FALSE the pathname would be: \dir1\test1.txt
*
* If node represents a named stream, construct the pathname for the
* associated unnamed stream then append the stream name.
*/
static int
{
int rc;
if (include_share) {
return (ENAMETOOLONG);
}
if (SMB_IS_STREAM(node))
else
return (0);
if (rc == 0) {
if (SMB_IS_STREAM(node))
}
return (rc);
}
/*
* smb_query_fileinfo
*
* Populate smb_queryinfo_t structure for SMB_FTYPE_DISK
* (This should become an smb_ofile / smb_node function.)
*/
int
{
int rc;
return (-1);
}
/*
* The number of links reported should be the number of
* non-deleted links. Thus if delete_on_close is set,
* decrement the link count.
*/
if (qinfo->qi_delete_on_close &&
}
/* populate name, namelen and shortname */
/* ALL_INFO levels include the sharename in the name field */
if ((infolev == SMB_QUERY_FILE_ALL_INFO) ||
(infolev == SMB_FILE_ALL_INFORMATION)) {
}
if (rc != 0) {
return (-1);
}
/*
* For some reason NT will not show the security tab in the root
* directory of a mapped drive unless the filename length is
* greater than one. So we hack the length here to persuade NT
* to show the tab. It should be safe because of the null
* terminator character.
*/
/*
* If the shortname is generated by smb_mangle_name()
* it will be returned as the alternative name.
* Otherwise, convert the original name to upper-case
* and return it as the alternative name.
*/
if (*qinfo->qi_shortname == 0) {
}
return (0);
}
/*
* smb_query_pipeinfo
*
* Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE
* (This should become an smb_opipe function.)
*/
static int
{
if ((infolev == SMB_INFO_STANDARD) ||
(infolev == SMB_INFO_QUERY_EA_SIZE) ||
(infolev == SMB_QUERY_INFORMATION2)) {
} else {
}
/* If the leading \ is missing from the pipe name, add it. */
if (*namep != '\\')
else
return (0);
}
/*
* smb_query_pipe_valid_infolev
*
* If the infolev is not valid for a message pipe, the error
* information is set in sr and B_FALSE is returned.
* Otherwise, returns B_TRUE.
*/
static boolean_t
{
switch (infolev) {
case SMB_INFO_QUERY_ALL_EAS:
return (B_FALSE);
return (B_FALSE);
}
return (B_TRUE);
}