2007-10-06 04:17:44 +04:00
/*
2007-08-26 19:16:40 +04:00
Unix SMB / CIFS implementation .
Registry interface
2007-10-06 04:17:44 +04:00
Copyright ( C ) Jelmer Vernooij 2004 - 2007.
2007-08-26 19:16:40 +04:00
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 3 of the License , or
( at your option ) any later version .
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
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 .
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2008-04-02 15:59:48 +04:00
# include "registry.h"
2007-08-26 19:16:40 +04:00
# include "system/dir.h"
# include "system/filesys.h"
struct dir_key {
struct hive_key key ;
const char * path ;
} ;
static struct hive_operations reg_backend_dir ;
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_add_key ( TALLOC_CTX * mem_ctx ,
const struct hive_key * parent ,
const char * name , const char * classname ,
struct security_descriptor * desc ,
struct hive_key * * result )
2007-08-26 19:16:40 +04:00
{
struct dir_key * dk = talloc_get_type ( parent , struct dir_key ) ;
char * path ;
int ret ;
path = talloc_asprintf ( mem_ctx , " %s/%s " , dk - > path , name ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( path ) ;
2007-08-26 19:16:40 +04:00
ret = mkdir ( path , 0700 ) ;
if ( ret = = 0 ) {
struct dir_key * key = talloc ( mem_ctx , struct dir_key ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( key ) ;
2007-08-26 19:16:40 +04:00
key - > key . ops = & reg_backend_dir ;
key - > path = talloc_steal ( key , path ) ;
* result = ( struct hive_key * ) key ;
return WERR_OK ;
}
if ( errno = = EEXIST )
return WERR_ALREADY_EXISTS ;
printf ( " FAILED %s BECAUSE: %s \n " , path , strerror ( errno ) ) ;
return WERR_GENERAL_FAILURE ;
}
2008-02-17 00:15:50 +03:00
static WERROR reg_dir_delete_recursive ( const char * name )
{
DIR * d ;
struct dirent * e ;
WERROR werr ;
d = opendir ( name ) ;
if ( d = = NULL ) {
DEBUG ( 3 , ( " Unable to open '%s': %s \n " , name ,
strerror ( errno ) ) ) ;
return WERR_BADFILE ;
}
while ( ( e = readdir ( d ) ) ) {
char * path ;
struct stat stbuf ;
if ( ISDOT ( e - > d_name ) | | ISDOTDOT ( e - > d_name ) )
continue ;
path = talloc_asprintf ( name , " %s/%s " , name , e - > d_name ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( path ) ;
2008-02-17 00:15:50 +03:00
stat ( path , & stbuf ) ;
if ( ! S_ISDIR ( stbuf . st_mode ) ) {
if ( unlink ( path ) < 0 ) {
talloc_free ( path ) ;
closedir ( d ) ;
return WERR_GENERAL_FAILURE ;
}
} else {
werr = reg_dir_delete_recursive ( path ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
talloc_free ( path ) ;
closedir ( d ) ;
return werr ;
}
}
talloc_free ( path ) ;
}
closedir ( d ) ;
if ( rmdir ( name ) = = 0 )
return WERR_OK ;
else if ( errno = = ENOENT )
return WERR_BADFILE ;
else
return WERR_GENERAL_FAILURE ;
}
2010-03-22 21:18:56 +03:00
static WERROR reg_dir_del_key ( TALLOC_CTX * mem_ctx , const struct hive_key * k ,
const char * name )
2007-08-26 19:16:40 +04:00
{
struct dir_key * dk = talloc_get_type ( k , struct dir_key ) ;
2010-03-22 21:26:59 +03:00
char * child ;
2007-08-26 19:16:40 +04:00
WERROR ret ;
2010-03-22 21:26:59 +03:00
child = talloc_asprintf ( mem_ctx , " %s/%s " , dk - > path , name ) ;
W_ERROR_HAVE_NO_MEMORY ( child ) ;
2008-02-17 00:15:50 +03:00
ret = reg_dir_delete_recursive ( child ) ;
2007-08-26 19:16:40 +04:00
talloc_free ( child ) ;
return ret ;
}
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_open_key ( TALLOC_CTX * mem_ctx ,
const struct hive_key * parent ,
const char * name , struct hive_key * * subkey )
2007-08-26 19:16:40 +04:00
{
DIR * d ;
char * fullpath ;
const struct dir_key * p = talloc_get_type ( parent , struct dir_key ) ;
struct dir_key * ret ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
if ( name = = NULL ) {
DEBUG ( 0 , ( " NULL pointer passed as directory name! " ) ) ;
return WERR_INVALID_PARAM ;
}
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
fullpath = talloc_asprintf ( mem_ctx , " %s/%s " , p - > path , name ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( fullpath ) ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
d = opendir ( fullpath ) ;
if ( d = = NULL ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 3 , ( " Unable to open '%s': %s \n " , fullpath ,
strerror ( errno ) ) ) ;
2010-03-22 21:26:59 +03:00
talloc_free ( fullpath ) ;
2007-08-26 19:16:40 +04:00
return WERR_BADFILE ;
}
closedir ( d ) ;
ret = talloc ( mem_ctx , struct dir_key ) ;
ret - > key . ops = & reg_backend_dir ;
ret - > path = talloc_steal ( ret , fullpath ) ;
* subkey = ( struct hive_key * ) ret ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_key_by_index ( TALLOC_CTX * mem_ctx ,
const struct hive_key * k , uint32_t idx ,
const char * * name ,
const char * * classname ,
NTTIME * last_mod_time )
2007-08-26 19:16:40 +04:00
{
struct dirent * e ;
const struct dir_key * dk = talloc_get_type ( k , struct dir_key ) ;
2009-11-07 23:07:20 +03:00
unsigned int i = 0 ;
2007-08-26 19:16:40 +04:00
DIR * d ;
d = opendir ( dk - > path ) ;
2007-10-06 04:17:44 +04:00
if ( d = = NULL )
2007-08-26 19:16:40 +04:00
return WERR_INVALID_PARAM ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
while ( ( e = readdir ( d ) ) ) {
if ( ! ISDOT ( e - > d_name ) & & ! ISDOTDOT ( e - > d_name ) ) {
struct stat stbuf ;
char * thispath ;
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
/* Check if file is a directory */
2010-03-22 21:26:59 +03:00
thispath = talloc_asprintf ( mem_ctx , " %s/%s " , dk - > path ,
e - > d_name ) ;
W_ERROR_HAVE_NO_MEMORY ( thispath ) ;
2007-08-26 19:16:40 +04:00
stat ( thispath , & stbuf ) ;
if ( ! S_ISDIR ( stbuf . st_mode ) ) {
2010-03-22 21:26:59 +03:00
talloc_free ( thispath ) ;
2007-08-26 19:16:40 +04:00
continue ;
}
if ( i = = idx ) {
struct stat st ;
* name = talloc_strdup ( mem_ctx , e - > d_name ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( * name ) ;
2007-08-26 19:16:40 +04:00
* classname = NULL ;
stat ( thispath , & st ) ;
unix_to_nt_time ( last_mod_time , st . st_mtime ) ;
2010-03-22 21:26:59 +03:00
talloc_free ( thispath ) ;
2007-08-26 19:16:40 +04:00
closedir ( d ) ;
return WERR_OK ;
}
i + + ;
2010-03-22 21:26:59 +03:00
talloc_free ( thispath ) ;
2007-08-26 19:16:40 +04:00
}
}
closedir ( d ) ;
return WERR_NO_MORE_ITEMS ;
}
2007-10-06 04:17:44 +04:00
WERROR reg_open_directory ( TALLOC_CTX * parent_ctx ,
const char * location , struct hive_key * * key )
2007-08-26 19:16:40 +04:00
{
struct dir_key * dk ;
2007-10-06 04:17:44 +04:00
if ( location = = NULL )
2007-08-26 19:16:40 +04:00
return WERR_INVALID_PARAM ;
dk = talloc ( parent_ctx , struct dir_key ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( dk ) ;
2007-08-26 19:16:40 +04:00
dk - > key . ops = & reg_backend_dir ;
dk - > path = talloc_strdup ( dk , location ) ;
* key = ( struct hive_key * ) dk ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
WERROR reg_create_directory ( TALLOC_CTX * parent_ctx ,
const char * location , struct hive_key * * key )
2007-08-26 19:16:40 +04:00
{
if ( mkdir ( location , 0700 ) ! = 0 ) {
* key = NULL ;
return WERR_GENERAL_FAILURE ;
}
return reg_open_directory ( parent_ctx , location , key ) ;
}
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_get_info ( TALLOC_CTX * ctx , const struct hive_key * key ,
const char * * classname ,
uint32_t * num_subkeys ,
uint32_t * num_values ,
2008-01-07 23:11:29 +03:00
NTTIME * lastmod ,
uint32_t * max_subkeynamelen ,
uint32_t * max_valnamelen ,
uint32_t * max_valbufsize )
2007-08-26 19:16:40 +04:00
{
DIR * d ;
const struct dir_key * dk = talloc_get_type ( key , struct dir_key ) ;
struct dirent * e ;
struct stat st ;
SMB_ASSERT ( key ! = NULL ) ;
if ( classname ! = NULL )
* classname = NULL ;
d = opendir ( dk - > path ) ;
2007-10-06 04:17:44 +04:00
if ( d = = NULL )
2007-08-26 19:16:40 +04:00
return WERR_INVALID_PARAM ;
if ( num_subkeys ! = NULL )
* num_subkeys = 0 ;
if ( num_values ! = NULL )
* num_values = 0 ;
2008-01-07 23:11:29 +03:00
if ( max_subkeynamelen ! = NULL )
* max_subkeynamelen = 0 ;
if ( max_valnamelen ! = NULL )
* max_valnamelen = 0 ;
if ( max_valbufsize ! = NULL )
* max_valbufsize = 0 ;
2007-08-26 19:16:40 +04:00
while ( ( e = readdir ( d ) ) ) {
if ( ! ISDOT ( e - > d_name ) & & ! ISDOTDOT ( e - > d_name ) ) {
2007-10-06 04:17:44 +04:00
char * path = talloc_asprintf ( ctx , " %s/%s " ,
dk - > path , e - > d_name ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( path ) ;
2007-08-26 19:16:40 +04:00
if ( stat ( path , & st ) < 0 ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 0 , ( " Error statting %s: %s \n " , path ,
strerror ( errno ) ) ) ;
2010-03-22 21:26:59 +03:00
talloc_free ( path ) ;
2007-08-26 19:16:40 +04:00
continue ;
}
2008-01-07 23:11:29 +03:00
if ( S_ISDIR ( st . st_mode ) ) {
if ( num_subkeys ! = NULL )
( * num_subkeys ) + + ;
if ( max_subkeynamelen ! = NULL )
* max_subkeynamelen = MAX ( * max_subkeynamelen , strlen ( e - > d_name ) ) ;
}
2007-08-26 19:16:40 +04:00
2008-01-07 23:11:29 +03:00
if ( ! S_ISDIR ( st . st_mode ) ) {
if ( num_values ! = NULL )
( * num_values ) + + ;
if ( max_valnamelen ! = NULL )
* max_valnamelen = MAX ( * max_valnamelen , strlen ( e - > d_name ) ) ;
if ( max_valbufsize ! = NULL )
* max_valbufsize = MAX ( * max_valbufsize , st . st_size ) ;
}
2007-08-26 19:16:40 +04:00
talloc_free ( path ) ;
}
}
closedir ( d ) ;
if ( lastmod ! = NULL )
* lastmod = 0 ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_set_value ( struct hive_key * key , const char * name ,
uint32_t type , const DATA_BLOB data )
2007-08-26 19:16:40 +04:00
{
const struct dir_key * dk = talloc_get_type ( key , struct dir_key ) ;
2010-03-22 21:26:59 +03:00
char * path ;
bool ret ;
path = talloc_asprintf ( dk , " %s/%s " , dk - > path , name ) ;
W_ERROR_HAVE_NO_MEMORY ( path ) ;
ret = file_save ( path , data . data , data . length ) ;
talloc_free ( path ) ;
2007-08-26 19:16:40 +04:00
2010-03-22 21:26:59 +03:00
if ( ! ret ) {
2007-08-26 19:16:40 +04:00
return WERR_GENERAL_FAILURE ;
2010-03-22 21:26:59 +03:00
}
2007-08-26 19:16:40 +04:00
/* FIXME: Type */
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_get_value ( TALLOC_CTX * mem_ctx ,
struct hive_key * key , const char * name ,
uint32_t * type , DATA_BLOB * data )
2007-08-26 19:16:40 +04:00
{
const struct dir_key * dk = talloc_get_type ( key , struct dir_key ) ;
2010-03-22 21:26:59 +03:00
char * path ;
2007-08-26 19:16:40 +04:00
size_t size ;
char * contents ;
2010-03-22 21:26:59 +03:00
path = talloc_asprintf ( mem_ctx , " %s/%s " , dk - > path , name ) ;
W_ERROR_HAVE_NO_MEMORY ( path ) ;
2008-10-12 19:34:43 +04:00
contents = file_load ( path , & size , 0 , mem_ctx ) ;
2010-03-22 21:26:59 +03:00
2007-08-26 19:16:40 +04:00
talloc_free ( path ) ;
2010-03-22 21:26:59 +03:00
2007-10-06 04:17:44 +04:00
if ( contents = = NULL )
2008-01-18 04:45:00 +03:00
return WERR_BADFILE ;
2007-08-26 19:16:40 +04:00
if ( type ! = NULL )
* type = 4 ; /* FIXME */
data - > data = ( uint8_t * ) contents ;
data - > length = size ;
return WERR_OK ;
}
2007-10-06 04:17:44 +04:00
static WERROR reg_dir_enum_value ( TALLOC_CTX * mem_ctx ,
2009-11-07 23:07:20 +03:00
struct hive_key * key , uint32_t idx ,
2007-10-06 04:17:44 +04:00
const char * * name ,
uint32_t * type , DATA_BLOB * data )
2007-08-26 19:16:40 +04:00
{
const struct dir_key * dk = talloc_get_type ( key , struct dir_key ) ;
DIR * d ;
struct dirent * e ;
2009-11-07 23:07:20 +03:00
unsigned int i ;
2007-08-26 19:16:40 +04:00
d = opendir ( dk - > path ) ;
if ( d = = NULL ) {
2007-10-06 04:17:44 +04:00
DEBUG ( 3 , ( " Unable to open '%s': %s \n " , dk - > path ,
strerror ( errno ) ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_BADFILE ;
}
i = 0 ;
while ( ( e = readdir ( d ) ) ) {
2007-10-06 04:17:44 +04:00
if ( ISDOT ( e - > d_name ) | | ISDOTDOT ( e - > d_name ) )
2007-08-26 19:16:40 +04:00
continue ;
if ( i = = idx ) {
2010-03-22 21:26:59 +03:00
if ( name ! = NULL ) {
2007-08-26 19:16:40 +04:00
* name = talloc_strdup ( mem_ctx , e - > d_name ) ;
2010-03-22 21:26:59 +03:00
W_ERROR_HAVE_NO_MEMORY ( * name ) ;
}
2007-10-06 04:17:44 +04:00
W_ERROR_NOT_OK_RETURN ( reg_dir_get_value ( mem_ctx , key ,
* name , type ,
data ) ) ;
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
i + + ;
}
closedir ( d ) ;
return WERR_NO_MORE_ITEMS ;
}
2010-03-22 21:18:56 +03:00
static WERROR reg_dir_del_value ( TALLOC_CTX * mem_ctx ,
struct hive_key * key , const char * name )
2007-08-26 19:16:40 +04:00
{
const struct dir_key * dk = talloc_get_type ( key , struct dir_key ) ;
2010-03-22 21:26:59 +03:00
char * path ;
int ret ;
path = talloc_asprintf ( mem_ctx , " %s/%s " , dk - > path , name ) ;
W_ERROR_HAVE_NO_MEMORY ( path ) ;
ret = unlink ( path ) ;
talloc_free ( path ) ;
if ( ret < 0 ) {
2007-08-26 19:16:40 +04:00
if ( errno = = ENOENT )
2008-01-18 05:37:06 +03:00
return WERR_BADFILE ;
2007-08-26 19:16:40 +04:00
return WERR_GENERAL_FAILURE ;
}
2007-10-06 04:17:44 +04:00
2007-08-26 19:16:40 +04:00
return WERR_OK ;
}
static struct hive_operations reg_backend_dir = {
. name = " dir " ,
. get_key_by_name = reg_dir_open_key ,
. get_key_info = reg_dir_get_info ,
. add_key = reg_dir_add_key ,
. del_key = reg_dir_del_key ,
. enum_key = reg_dir_key_by_index ,
. set_value = reg_dir_set_value ,
. get_value_by_name = reg_dir_get_value ,
. enum_value = reg_dir_enum_value ,
. delete_value = reg_dir_del_value ,
} ;