2004-09-18 08:16:14 +00:00
/*
Unix SMB / CIFS implementation .
POSIX NTVFS backend - directory search functions
Copyright ( C ) Andrew Tridgell 2004
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "include/includes.h"
# include "vfs_posix.h"
2004-10-19 06:39:51 +00:00
/*
destroy an open search
*/
static int pvfs_search_destructor ( void * ptr )
{
struct pvfs_search_state * search = ptr ;
idr_remove ( search - > pvfs - > idtree_search , search - > handle ) ;
return 0 ;
}
2004-09-18 08:16:14 +00:00
/*
fill in a single search result for a given info level
*/
static NTSTATUS fill_search_info ( struct pvfs_state * pvfs ,
enum smb_search_level level ,
const char * unix_path ,
2004-09-20 07:28:43 +00:00
const char * fname ,
2004-09-22 12:38:19 +00:00
struct pvfs_search_state * search ,
2004-09-18 08:16:14 +00:00
uint32_t dir_index ,
union smb_search_data * file )
{
2004-09-20 07:28:43 +00:00
struct pvfs_filename * name ;
2004-09-18 08:16:14 +00:00
NTSTATUS status ;
2004-10-11 03:27:16 +00:00
const char * shortname ;
2004-09-18 08:16:14 +00:00
2004-09-20 07:28:43 +00:00
status = pvfs_resolve_partial ( pvfs , file , unix_path , fname , & name ) ;
2004-09-18 08:16:14 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-09-20 07:28:43 +00:00
2004-09-22 12:38:19 +00:00
if ( ! pvfs_match_attrib ( pvfs , name , search - > search_attrib ) ) {
2004-09-22 08:17:26 +00:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2004-09-18 08:16:14 +00:00
switch ( level ) {
2004-09-22 12:38:19 +00:00
case RAW_SEARCH_SEARCH :
case RAW_SEARCH_FFIRST :
case RAW_SEARCH_FUNIQUE :
2004-10-11 03:27:16 +00:00
shortname = pvfs_short_name ( pvfs , name , name ) ;
2004-09-22 12:38:19 +00:00
file - > search . attrib = name - > dos . attrib ;
file - > search . write_time = nt_time_to_unix ( name - > dos . write_time ) ;
file - > search . size = name - > st . st_size ;
2004-10-11 03:27:16 +00:00
file - > search . name = shortname ;
2004-09-22 12:38:19 +00:00
file - > search . id . reserved = 8 ;
memset ( file - > search . id . name , ' ' , sizeof ( file - > search . id . name ) ) ;
2004-10-11 03:27:16 +00:00
memcpy ( file - > search . id . name , shortname ,
MIN ( strlen ( shortname ) + 1 , sizeof ( file - > search . id . name ) ) ) ;
2004-09-22 12:38:19 +00:00
file - > search . id . handle = search - > handle ;
file - > search . id . server_cookie = dir_index + 1 ;
file - > search . id . client_cookie = 0 ;
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_STANDARD :
2004-09-22 12:38:19 +00:00
file - > standard . resume_key = dir_index + 1 ;
2004-09-22 08:17:26 +00:00
file - > standard . create_time = nt_time_to_unix ( name - > dos . create_time ) ;
file - > standard . access_time = nt_time_to_unix ( name - > dos . access_time ) ;
file - > standard . write_time = nt_time_to_unix ( name - > dos . write_time ) ;
file - > standard . size = name - > st . st_size ;
file - > standard . alloc_size = name - > dos . alloc_size ;
file - > standard . attrib = name - > dos . attrib ;
file - > standard . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_EA_SIZE :
2004-09-22 12:38:19 +00:00
file - > ea_size . resume_key = dir_index + 1 ;
2004-09-22 08:17:26 +00:00
file - > ea_size . create_time = nt_time_to_unix ( name - > dos . create_time ) ;
file - > ea_size . access_time = nt_time_to_unix ( name - > dos . access_time ) ;
file - > ea_size . write_time = nt_time_to_unix ( name - > dos . write_time ) ;
file - > ea_size . size = name - > st . st_size ;
file - > ea_size . alloc_size = name - > dos . alloc_size ;
file - > ea_size . attrib = name - > dos . attrib ;
file - > ea_size . ea_size = name - > dos . ea_size ;
file - > ea_size . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_DIRECTORY_INFO :
2004-09-22 12:38:19 +00:00
file - > directory_info . file_index = dir_index + 1 ;
2004-09-22 08:17:26 +00:00
file - > directory_info . create_time = name - > dos . create_time ;
file - > directory_info . access_time = name - > dos . access_time ;
file - > directory_info . write_time = name - > dos . write_time ;
file - > directory_info . change_time = name - > dos . change_time ;
file - > directory_info . size = name - > st . st_size ;
file - > directory_info . alloc_size = name - > dos . alloc_size ;
file - > directory_info . attrib = name - > dos . attrib ;
file - > directory_info . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_FULL_DIRECTORY_INFO :
2004-09-22 12:38:19 +00:00
file - > full_directory_info . file_index = dir_index + 1 ;
2004-09-22 08:17:26 +00:00
file - > full_directory_info . create_time = name - > dos . create_time ;
file - > full_directory_info . access_time = name - > dos . access_time ;
file - > full_directory_info . write_time = name - > dos . write_time ;
file - > full_directory_info . change_time = name - > dos . change_time ;
file - > full_directory_info . size = name - > st . st_size ;
file - > full_directory_info . alloc_size = name - > dos . alloc_size ;
file - > full_directory_info . attrib = name - > dos . attrib ;
file - > full_directory_info . ea_size = name - > dos . ea_size ;
file - > full_directory_info . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_NAME_INFO :
file - > name_info . file_index = dir_index ;
file - > name_info . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-18 08:16:14 +00:00
case RAW_SEARCH_BOTH_DIRECTORY_INFO :
2004-09-22 12:38:19 +00:00
file - > both_directory_info . file_index = dir_index + 1 ;
2004-09-20 07:28:43 +00:00
file - > both_directory_info . create_time = name - > dos . create_time ;
file - > both_directory_info . access_time = name - > dos . access_time ;
file - > both_directory_info . write_time = name - > dos . write_time ;
file - > both_directory_info . change_time = name - > dos . change_time ;
file - > both_directory_info . size = name - > st . st_size ;
file - > both_directory_info . alloc_size = name - > dos . alloc_size ;
file - > both_directory_info . attrib = name - > dos . attrib ;
file - > both_directory_info . ea_size = name - > dos . ea_size ;
2004-10-02 13:29:20 +00:00
file - > both_directory_info . short_name . s = pvfs_short_name ( pvfs , file , name ) ;
2004-09-20 07:28:43 +00:00
file - > both_directory_info . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_ID_FULL_DIRECTORY_INFO :
2004-09-22 12:38:19 +00:00
file - > id_full_directory_info . file_index = dir_index + 1 ;
2004-09-22 08:17:26 +00:00
file - > id_full_directory_info . create_time = name - > dos . create_time ;
file - > id_full_directory_info . access_time = name - > dos . access_time ;
file - > id_full_directory_info . write_time = name - > dos . write_time ;
file - > id_full_directory_info . change_time = name - > dos . change_time ;
file - > id_full_directory_info . size = name - > st . st_size ;
file - > id_full_directory_info . alloc_size = name - > dos . alloc_size ;
file - > id_full_directory_info . attrib = name - > dos . attrib ;
file - > id_full_directory_info . ea_size = name - > dos . ea_size ;
file - > id_full_directory_info . file_id = name - > dos . file_id ;
file - > id_full_directory_info . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-22 08:17:26 +00:00
case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO :
2004-09-22 12:38:19 +00:00
file - > id_both_directory_info . file_index = dir_index + 1 ;
2004-09-22 08:17:26 +00:00
file - > id_both_directory_info . create_time = name - > dos . create_time ;
file - > id_both_directory_info . access_time = name - > dos . access_time ;
file - > id_both_directory_info . write_time = name - > dos . write_time ;
file - > id_both_directory_info . change_time = name - > dos . change_time ;
file - > id_both_directory_info . size = name - > st . st_size ;
file - > id_both_directory_info . alloc_size = name - > dos . alloc_size ;
file - > id_both_directory_info . attrib = name - > dos . attrib ;
file - > id_both_directory_info . ea_size = name - > dos . ea_size ;
file - > id_both_directory_info . file_id = name - > dos . file_id ;
2004-10-02 13:29:20 +00:00
file - > id_both_directory_info . short_name . s = pvfs_short_name ( pvfs , file , name ) ;
2004-09-22 08:17:26 +00:00
file - > id_both_directory_info . name . s = fname ;
2004-09-22 12:38:19 +00:00
return NT_STATUS_OK ;
2004-09-18 08:16:14 +00:00
2004-09-22 12:38:19 +00:00
case RAW_SEARCH_GENERIC :
break ;
2004-09-18 08:16:14 +00:00
}
2004-09-22 12:38:19 +00:00
return NT_STATUS_INVALID_LEVEL ;
2004-09-18 08:16:14 +00:00
}
2004-09-22 08:17:26 +00:00
/*
the search fill loop
*/
static NTSTATUS pvfs_search_fill ( struct pvfs_state * pvfs , TALLOC_CTX * mem_ctx ,
uint_t max_count ,
struct pvfs_search_state * search ,
enum smb_search_level level ,
uint_t * reply_count ,
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
int i ;
struct pvfs_dir * dir = search - > dir ;
NTSTATUS status ;
* reply_count = 0 ;
for ( i = search - > current_index ; i < dir - > count ; i + + ) {
union smb_search_data * file ;
file = talloc_p ( mem_ctx , union smb_search_data ) ;
if ( ! file ) {
return NT_STATUS_NO_MEMORY ;
}
status = fill_search_info ( pvfs , level , dir - > unix_path , dir - > names [ i ] ,
2004-09-22 12:38:19 +00:00
search , i , file ) ;
2004-09-22 08:17:26 +00:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
talloc_free ( file ) ;
continue ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( file ) ;
search - > current_index = i ;
return status ;
}
if ( ! callback ( search_private , file ) ) {
talloc_free ( file ) ;
break ;
}
( * reply_count ) + + ;
talloc_free ( file ) ;
/* note that this deliberately allows a reply_count of
1 for a max_count of 0. w2k3 allows this too . */
if ( * reply_count > = max_count ) break ;
}
search - > current_index = i ;
return NT_STATUS_OK ;
}
2004-09-22 12:38:19 +00:00
/*
list files in a directory matching a wildcard pattern - old SMBsearch interface
*/
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_search_first_old ( struct ntvfs_module_context * ntvfs ,
struct smbsrv_request * req , union smb_search_first * io ,
2004-09-22 12:38:19 +00:00
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
struct pvfs_dir * dir ;
2004-09-29 13:17:09 +00:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-22 12:38:19 +00:00
struct pvfs_search_state * search ;
uint_t reply_count ;
uint16_t search_attrib ;
const char * pattern ;
NTSTATUS status ;
struct pvfs_filename * name ;
2004-10-19 06:39:51 +00:00
int id ;
2004-09-22 12:38:19 +00:00
search_attrib = io - > search_first . in . search_attrib ;
pattern = io - > search_first . in . pattern ;
/* resolve the cifs name to a posix name */
status = pvfs_resolve_name ( pvfs , req , pattern , 0 , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! name - > has_wildcard & & ! name - > exists ) {
return STATUS_NO_MORE_FILES ;
}
/* we initially make search a child of the request, then if we
need to keep it long term we steal it for the private
structure */
search = talloc_p ( req , struct pvfs_search_state ) ;
if ( ! search ) {
return NT_STATUS_NO_MEMORY ;
}
dir = talloc_p ( search , struct pvfs_dir ) ;
if ( ! dir ) {
return NT_STATUS_NO_MEMORY ;
}
/* do the actual directory listing */
status = pvfs_list ( pvfs , name , dir ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* we need to give a handle back to the client so it
can continue a search */
2004-10-19 12:06:01 +00:00
id = idr_get_new ( pvfs - > idtree_search , search , UINT8_MAX ) ;
2004-10-19 06:39:51 +00:00
if ( id = = - 1 ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
2004-09-22 12:38:19 +00:00
}
2004-10-19 06:39:51 +00:00
search - > pvfs = pvfs ;
search - > handle = id ;
2004-09-22 12:38:19 +00:00
search - > dir = dir ;
search - > current_index = 0 ;
search - > search_attrib = search_attrib ;
2004-10-19 06:39:51 +00:00
talloc_set_destructor ( search , pvfs_search_destructor ) ;
2004-09-22 12:38:19 +00:00
status = pvfs_search_fill ( pvfs , req , io - > search_first . in . max_count , search , io - > generic . level ,
& reply_count , search_private , callback ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
io - > search_first . out . count = reply_count ;
/* not matching any entries is an error */
if ( reply_count = = 0 ) {
return STATUS_NO_MORE_FILES ;
}
talloc_steal ( pvfs , search ) ;
return NT_STATUS_OK ;
}
/* continue a old style search */
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_search_next_old ( struct ntvfs_module_context * ntvfs ,
struct smbsrv_request * req , union smb_search_next * io ,
2004-09-22 12:38:19 +00:00
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
2004-09-29 13:17:09 +00:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-22 12:38:19 +00:00
struct pvfs_search_state * search ;
struct pvfs_dir * dir ;
uint_t reply_count , max_count ;
uint16_t handle ;
NTSTATUS status ;
handle = io - > search_next . in . id . handle ;
max_count = io - > search_next . in . max_count ;
2004-10-19 06:39:51 +00:00
search = idr_find ( pvfs - > idtree_search , handle ) ;
if ( search = = NULL ) {
2004-09-22 12:38:19 +00:00
/* we didn't find the search handle */
return NT_STATUS_INVALID_HANDLE ;
}
search - > current_index = io - > search_next . in . id . server_cookie ;
dir = search - > dir ;
status = pvfs_search_fill ( pvfs , req , max_count , search , io - > generic . level ,
& reply_count , search_private , callback ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
io - > search_next . out . count = reply_count ;
/* not matching any entries means end of search */
if ( reply_count = = 0 ) {
talloc_free ( search ) ;
}
return NT_STATUS_OK ;
}
2004-09-18 08:16:14 +00:00
/*
list files in a directory matching a wildcard pattern
*/
2004-09-29 13:17:09 +00:00
NTSTATUS pvfs_search_first ( struct ntvfs_module_context * ntvfs ,
struct smbsrv_request * req , union smb_search_first * io ,
2004-09-18 08:16:14 +00:00
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
struct pvfs_dir * dir ;
2004-09-29 13:17:09 +00:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-18 08:16:14 +00:00
struct pvfs_search_state * search ;
2004-09-22 08:17:26 +00:00
uint_t reply_count ;
2004-09-22 12:38:19 +00:00
uint16_t search_attrib , max_count ;
2004-09-18 08:16:14 +00:00
const char * pattern ;
NTSTATUS status ;
struct pvfs_filename * name ;
2004-10-19 06:39:51 +00:00
int id ;
2004-09-18 08:16:14 +00:00
2004-09-22 08:17:26 +00:00
if ( io - > generic . level > = RAW_SEARCH_SEARCH ) {
2004-09-29 13:17:09 +00:00
return pvfs_search_first_old ( ntvfs , req , io , search_private , callback ) ;
2004-09-18 08:16:14 +00:00
}
2004-09-22 08:17:26 +00:00
search_attrib = io - > t2ffirst . in . search_attrib ;
pattern = io - > t2ffirst . in . pattern ;
2004-09-22 12:38:19 +00:00
max_count = io - > t2ffirst . in . max_count ;
2004-09-22 08:17:26 +00:00
2004-09-18 08:16:14 +00:00
/* resolve the cifs name to a posix name */
status = pvfs_resolve_name ( pvfs , req , pattern , 0 , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! name - > has_wildcard & & ! name - > exists ) {
2004-09-22 08:17:26 +00:00
return NT_STATUS_NO_SUCH_FILE ;
2004-09-18 08:16:14 +00:00
}
/* we initially make search a child of the request, then if we
need to keep it long term we steal it for the private
structure */
search = talloc_p ( req , struct pvfs_search_state ) ;
if ( ! search ) {
return NT_STATUS_NO_MEMORY ;
}
dir = talloc_p ( search , struct pvfs_dir ) ;
if ( ! dir ) {
return NT_STATUS_NO_MEMORY ;
}
/* do the actual directory listing */
status = pvfs_list ( pvfs , name , dir ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-10-19 12:06:01 +00:00
id = idr_get_new ( pvfs - > idtree_search , search , UINT16_MAX ) ;
2004-10-19 06:39:51 +00:00
if ( id = = - 1 ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
2004-09-18 08:16:14 +00:00
}
2004-10-19 06:39:51 +00:00
search - > pvfs = pvfs ;
search - > handle = id ;
2004-09-18 08:16:14 +00:00
search - > dir = dir ;
search - > current_index = 0 ;
search - > search_attrib = search_attrib ;
2004-10-19 06:39:51 +00:00
talloc_set_destructor ( search , pvfs_search_destructor ) ;
2004-09-22 12:38:19 +00:00
status = pvfs_search_fill ( pvfs , req , max_count , search , io - > generic . level ,
2004-09-22 08:17:26 +00:00
& reply_count , search_private , callback ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-09-18 08:16:14 +00:00
}
/* not matching any entries is an error */
if ( reply_count = = 0 ) {
2004-09-22 08:17:26 +00:00
return NT_STATUS_NO_SUCH_FILE ;
2004-09-18 08:16:14 +00:00
}
2004-09-22 08:17:26 +00:00
io - > t2ffirst . out . count = reply_count ;
io - > t2ffirst . out . handle = search - > handle ;
io - > t2ffirst . out . end_of_search = ( search - > current_index = = dir - > count ) ? 1 : 0 ;
2004-09-18 08:16:14 +00:00
2004-09-22 08:17:26 +00:00
/* work out if we are going to keep the search state
and allow for a search continue */
if ( ( io - > t2ffirst . in . flags & FLAG_TRANS2_FIND_CLOSE ) | |
( ( io - > t2ffirst . in . flags & FLAG_TRANS2_FIND_CLOSE_IF_END ) & &
io - > t2ffirst . out . end_of_search ) ) {
talloc_free ( search ) ;
2004-09-18 08:16:14 +00:00
} else {
2004-09-22 08:17:26 +00:00
talloc_steal ( pvfs , search ) ;
2004-09-18 08:16:14 +00:00
}
return NT_STATUS_OK ;
}
/* continue a search */
2004-09-29 13:17:09 +00:00
NTSTATUS pvfs_search_next ( struct ntvfs_module_context * ntvfs ,
struct smbsrv_request * req , union smb_search_next * io ,
2004-09-18 08:16:14 +00:00
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
2004-09-29 13:17:09 +00:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-22 08:17:26 +00:00
struct pvfs_search_state * search ;
struct pvfs_dir * dir ;
uint_t reply_count ;
2004-09-21 08:46:47 +00:00
uint16_t handle ;
2004-09-22 08:17:26 +00:00
NTSTATUS status ;
2004-09-21 08:46:47 +00:00
int i ;
2004-09-22 08:17:26 +00:00
if ( io - > generic . level > = RAW_SEARCH_SEARCH ) {
2004-09-29 13:17:09 +00:00
return pvfs_search_next_old ( ntvfs , req , io , search_private , callback ) ;
2004-09-21 08:46:47 +00:00
}
2004-09-22 08:17:26 +00:00
handle = io - > t2fnext . in . handle ;
2004-09-21 08:46:47 +00:00
2004-10-19 06:39:51 +00:00
search = idr_find ( pvfs - > idtree_search , handle ) ;
if ( search = = NULL ) {
2004-09-21 08:46:47 +00:00
/* we didn't find the search handle */
2004-09-22 08:17:26 +00:00
return NT_STATUS_INVALID_HANDLE ;
2004-09-21 08:46:47 +00:00
}
dir = search - > dir ;
2004-09-22 12:38:19 +00:00
/* work out what type of continuation is being used */
if ( io - > t2fnext . in . last_name & & * io - > t2fnext . in . last_name ) {
2004-09-21 08:46:47 +00:00
/* look backwards first */
for ( i = search - > current_index ; i > 0 ; i - - ) {
2004-09-22 08:17:26 +00:00
if ( strcmp ( io - > t2fnext . in . last_name , dir - > names [ i - 1 ] ) = = 0 ) {
2004-09-21 08:46:47 +00:00
search - > current_index = i ;
goto found ;
}
}
/* then look forwards */
for ( i = search - > current_index + 1 ; i < = dir - > count ; i + + ) {
2004-09-22 08:17:26 +00:00
if ( strcmp ( io - > t2fnext . in . last_name , dir - > names [ i - 1 ] ) = = 0 ) {
2004-09-21 08:46:47 +00:00
search - > current_index = i ;
goto found ;
}
}
2004-09-22 12:38:19 +00:00
} else if ( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_CONTINUE ) {
/* plain continue - nothing to do */
} else {
search - > current_index = io - > t2fnext . in . resume_key ;
2004-09-21 08:46:47 +00:00
}
found :
2004-09-22 08:17:26 +00:00
status = pvfs_search_fill ( pvfs , req , io - > t2fnext . in . max_count , search , io - > generic . level ,
& reply_count , search_private , callback ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-09-21 08:46:47 +00:00
}
2004-09-22 08:17:26 +00:00
/* not matching any entries is an error */
if ( reply_count = = 0 ) {
return NT_STATUS_NO_MORE_ENTRIES ;
2004-09-21 08:46:47 +00:00
}
2004-09-22 08:17:26 +00:00
io - > t2fnext . out . count = reply_count ;
io - > t2fnext . out . end_of_search = ( search - > current_index = = dir - > count ) ? 1 : 0 ;
2004-09-21 08:46:47 +00:00
/* work out if we are going to keep the search state */
if ( ( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_CLOSE ) | |
2004-09-22 08:17:26 +00:00
( ( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_CLOSE_IF_END ) & &
io - > t2fnext . out . end_of_search ) ) {
2004-09-21 08:46:47 +00:00
talloc_free ( search ) ;
}
2004-09-22 08:17:26 +00:00
2004-09-21 08:46:47 +00:00
return NT_STATUS_OK ;
2004-09-18 08:16:14 +00:00
}
/* close a search */
2004-09-29 13:17:09 +00:00
NTSTATUS pvfs_search_close ( struct ntvfs_module_context * ntvfs ,
struct smbsrv_request * req , union smb_search_close * io )
2004-09-18 08:16:14 +00:00
{
2004-09-29 13:17:09 +00:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-22 08:17:26 +00:00
struct pvfs_search_state * search ;
uint16_t handle ;
2004-09-22 12:38:19 +00:00
if ( io - > generic . level = = RAW_FINDCLOSE_FCLOSE ) {
handle = io - > fclose . in . id . handle ;
} else {
handle = io - > findclose . in . handle ;
2004-09-22 08:17:26 +00:00
}
2004-10-19 06:39:51 +00:00
search = idr_find ( pvfs - > idtree_search , handle ) ;
if ( search = = NULL ) {
2004-09-22 08:17:26 +00:00
/* we didn't find the search handle */
return NT_STATUS_INVALID_HANDLE ;
}
talloc_free ( search ) ;
return NT_STATUS_OK ;
2004-09-18 08:16:14 +00:00
}