2005-09-06 00:36:07 +04:00
/*
Samba share mode database library external interface library .
Used by non - Samba products needing access to the Samba share mode db .
2009-01-01 21:47:40 +03:00
2006-02-04 09:31:04 +03:00
Copyright ( C ) Jeremy Allison 2005 - 2006
2005-10-29 00:36:21 +04:00
sharemodes_procid functions ( C ) Copyright ( C ) Volker Lendecke 2005
* * NOTE ! The following LGPL license applies to this module only .
* * This does NOT imply that all of Samba is released
* * under the LGPL
2009-01-01 21:47:40 +03:00
2005-09-06 00:36:07 +04:00
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
2007-07-10 05:44:42 +04:00
version 3 of the License , or ( at your option ) any later version .
2009-01-01 21:47:40 +03:00
2005-09-06 00:36:07 +04:00
This library 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
Lesser General Public License for more details .
2009-01-01 21:47:40 +03:00
2005-09-06 00:36:07 +04:00
You should have received a copy of the GNU Lesser General Public
2007-07-10 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2005-09-06 00:36:07 +04:00
*/
# include "includes.h"
# include "smb_share_modes.h"
2007-04-10 22:12:25 +04:00
/* Database context handle. */
struct smbdb_ctx {
TDB_CONTEXT * smb_tdb ;
} ;
2005-09-10 01:49:49 +04:00
/* Remove the paranoid malloc checker. */
# ifdef malloc
# undef malloc
# endif
2006-12-20 04:10:04 +03:00
int smb_create_share_mode_entry_ex ( struct smbdb_ctx * db_ctx , uint64_t dev ,
2009-02-16 10:45:28 +03:00
uint64_t ino , uint64_t extid ,
const struct smb_share_mode_entry * new_entry ,
2006-12-20 04:10:04 +03:00
const char * sharepath , const char * filename ) ;
2007-10-19 04:40:25 +04:00
static bool sharemodes_procid_equal ( const struct server_id * p1 , const struct server_id * p2 )
2005-10-29 00:36:21 +04:00
{
return ( p1 - > pid = = p2 - > pid ) ;
}
2007-05-07 13:35:35 +04:00
static pid_t sharemodes_procid_to_pid ( const struct server_id * proc )
2005-10-29 00:36:21 +04:00
{
return proc - > pid ;
}
2005-09-06 00:36:07 +04:00
/*
* open / close sharemode database .
*/
struct smbdb_ctx * smb_share_mode_db_open ( const char * db_path )
{
2005-09-10 01:49:49 +04:00
struct smbdb_ctx * smb_db = ( struct smbdb_ctx * ) malloc ( sizeof ( struct smbdb_ctx ) ) ;
2005-09-06 00:36:07 +04:00
if ( ! smb_db ) {
return NULL ;
}
memset ( smb_db , ' \0 ' , sizeof ( struct smbdb_ctx ) ) ;
2005-09-10 01:49:49 +04:00
smb_db - > smb_tdb = tdb_open ( db_path ,
2010-09-27 16:46:07 +04:00
0 , TDB_DEFAULT | TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH ,
2005-09-06 00:36:07 +04:00
O_RDWR | O_CREAT ,
0644 ) ;
if ( ! smb_db - > smb_tdb ) {
free ( smb_db ) ;
return NULL ;
}
/* Should check that this is the correct version.... */
return smb_db ;
}
2005-09-30 21:13:37 +04:00
/* key and data records in the tdb locking database */
struct locking_key {
SMB_DEV_T dev ;
SMB_INO_T inode ;
2009-02-16 10:45:28 +03:00
uint64_t extid ;
2005-09-30 21:13:37 +04:00
} ;
2005-09-06 00:36:07 +04:00
int smb_share_mode_db_close ( struct smbdb_ctx * db_ctx )
{
int ret = tdb_close ( db_ctx - > smb_tdb ) ;
free ( db_ctx ) ;
return ret ;
}
2009-01-01 21:55:20 +03:00
static TDB_DATA get_locking_key ( struct locking_key * lk , uint64_t dev ,
2009-02-16 10:45:28 +03:00
uint64_t ino , uint64_t extid )
2005-09-06 00:36:07 +04:00
{
TDB_DATA ld ;
2009-01-01 21:55:20 +03:00
memset ( lk , ' \0 ' , sizeof ( * lk ) ) ;
lk - > dev = ( SMB_DEV_T ) dev ;
lk - > inode = ( SMB_INO_T ) ino ;
2009-02-16 10:45:28 +03:00
lk - > extid = extid ;
2009-01-01 21:55:20 +03:00
ld . dptr = ( uint8 * ) lk ;
ld . dsize = sizeof ( * lk ) ;
2005-09-06 00:36:07 +04:00
return ld ;
}
/*
* lock / unlock entry in sharemode database .
*/
int smb_lock_share_mode_entry ( struct smbdb_ctx * db_ctx ,
uint64_t dev ,
2009-02-16 10:45:28 +03:00
uint64_t ino ,
uint64_t extid )
2005-09-06 00:36:07 +04:00
{
2009-01-01 21:55:20 +03:00
struct locking_key lk ;
2009-02-16 10:45:28 +03:00
return tdb_chainlock ( db_ctx - > smb_tdb , get_locking_key ( & lk , dev , ino ,
extid ) ) ;
2005-09-06 00:36:07 +04:00
}
2009-01-01 21:47:40 +03:00
2005-09-06 00:36:07 +04:00
int smb_unlock_share_mode_entry ( struct smbdb_ctx * db_ctx ,
2005-09-11 09:16:54 +04:00
uint64_t dev ,
2009-02-16 10:45:28 +03:00
uint64_t ino ,
uint64_t extid )
2005-09-06 00:36:07 +04:00
{
2009-01-01 21:55:20 +03:00
struct locking_key lk ;
return tdb_chainunlock ( db_ctx - > smb_tdb ,
2009-02-16 10:45:28 +03:00
get_locking_key ( & lk , dev , ino , extid ) ) ;
2005-09-06 00:36:07 +04:00
}
/*
* Check if an external smb_share_mode_entry and an internal share_mode entry match .
*/
2006-02-04 09:31:04 +03:00
static int share_mode_entry_equal ( const struct smb_share_mode_entry * e_entry ,
const struct share_mode_entry * entry )
2005-09-06 00:36:07 +04:00
{
2005-10-29 00:36:21 +04:00
return ( sharemodes_procid_equal ( & e_entry - > pid , & entry - > pid ) & &
2005-09-06 00:36:07 +04:00
e_entry - > file_id = = ( uint32_t ) entry - > share_file_id & &
e_entry - > open_time . tv_sec = = entry - > time . tv_sec & &
e_entry - > open_time . tv_usec = = entry - > time . tv_usec & &
e_entry - > share_access = = ( uint32_t ) entry - > share_access & &
e_entry - > access_mask = = ( uint32_t ) entry - > access_mask & &
2007-05-29 13:30:34 +04:00
e_entry - > dev = = entry - > id . devid & &
2009-02-16 10:45:28 +03:00
e_entry - > ino = = entry - > id . inode & &
e_entry - > extid = = entry - > id . extid ) ;
2005-09-06 00:36:07 +04:00
}
/*
* Create an internal Samba share_mode entry from an external smb_share_mode_entry .
*/
2006-02-04 09:31:04 +03:00
static void create_share_mode_entry ( struct share_mode_entry * out ,
const struct smb_share_mode_entry * in )
2005-09-06 00:36:07 +04:00
{
2005-09-30 21:13:37 +04:00
memset ( out , ' \0 ' , sizeof ( struct share_mode_entry ) ) ;
2005-09-06 00:36:07 +04:00
out - > pid = in - > pid ;
out - > share_file_id = ( unsigned long ) in - > file_id ;
out - > time . tv_sec = in - > open_time . tv_sec ;
out - > time . tv_usec = in - > open_time . tv_usec ;
out - > share_access = in - > share_access ;
out - > access_mask = in - > access_mask ;
2007-05-29 13:30:34 +04:00
out - > id . devid = in - > dev ;
out - > id . inode = in - > ino ;
2009-02-16 10:45:28 +03:00
out - > id . extid = in - > extid ;
2006-06-21 06:31:12 +04:00
out - > uid = ( uint32 ) geteuid ( ) ;
2007-02-07 00:05:34 +03:00
out - > flags = 0 ;
2005-09-06 00:36:07 +04:00
}
/*
* Return the current share mode list for an open file .
* This uses similar ( but simplified ) logic to locking / locking . c
*/
int smb_get_share_mode_entries ( struct smbdb_ctx * db_ctx ,
uint64_t dev ,
uint64_t ino ,
2009-02-16 10:45:28 +03:00
uint64_t extid ,
2005-09-06 00:36:07 +04:00
struct smb_share_mode_entry * * pp_list ,
unsigned char * p_delete_on_close )
{
2009-01-01 21:55:20 +03:00
struct locking_key lk ;
2005-09-06 00:36:07 +04:00
TDB_DATA db_data ;
struct smb_share_mode_entry * list = NULL ;
int num_share_modes = 0 ;
struct locking_data * ld = NULL ; /* internal samba db state. */
2005-09-30 21:13:37 +04:00
struct share_mode_entry * shares = NULL ;
2005-09-06 00:36:07 +04:00
size_t i ;
2005-09-14 02:23:59 +04:00
int list_num ;
2005-09-06 00:36:07 +04:00
* pp_list = NULL ;
* p_delete_on_close = 0 ;
2009-02-16 10:45:28 +03:00
db_data = tdb_fetch ( db_ctx - > smb_tdb , get_locking_key ( & lk , dev , ino ,
extid ) ) ;
2005-09-06 00:36:07 +04:00
if ( ! db_data . dptr ) {
return 0 ;
}
ld = ( struct locking_data * ) db_data . dptr ;
num_share_modes = ld - > u . s . num_share_mode_entries ;
if ( ! num_share_modes ) {
free ( db_data . dptr ) ;
return 0 ;
}
2005-09-10 01:49:49 +04:00
list = ( struct smb_share_mode_entry * ) malloc ( sizeof ( struct smb_share_mode_entry ) * num_share_modes ) ;
2005-09-06 00:36:07 +04:00
if ( ! list ) {
free ( db_data . dptr ) ;
return - 1 ;
}
memset ( list , ' \0 ' , num_share_modes * sizeof ( struct smb_share_mode_entry ) ) ;
2007-03-30 02:12:28 +04:00
shares = ( struct share_mode_entry * ) ( db_data . dptr + sizeof ( struct locking_data ) ) ;
2005-09-06 00:36:07 +04:00
2005-09-14 02:23:59 +04:00
list_num = 0 ;
2005-09-06 00:36:07 +04:00
for ( i = 0 ; i < num_share_modes ; i + + ) {
2005-09-30 21:13:37 +04:00
struct share_mode_entry * share = & shares [ i ] ;
2005-09-14 02:23:59 +04:00
struct smb_share_mode_entry * sme = & list [ list_num ] ;
2007-05-07 13:35:35 +04:00
struct server_id pid = share - > pid ;
2005-09-06 00:36:07 +04:00
/* Check this process really exists. */
2005-10-29 00:36:21 +04:00
if ( kill ( sharemodes_procid_to_pid ( & pid ) , 0 ) = = - 1 & & ( errno = = ESRCH ) ) {
2005-09-06 00:36:07 +04:00
continue ; /* No longer exists. */
}
2005-09-30 21:13:37 +04:00
/* Ignore deferred open entries. */
if ( share - > op_type = = DEFERRED_OPEN_ENTRY ) {
continue ;
}
2005-09-06 00:36:07 +04:00
/* Copy into the external list. */
2007-05-29 13:30:34 +04:00
sme - > dev = share - > id . devid ;
sme - > ino = share - > id . inode ;
2009-02-16 10:45:28 +03:00
sme - > extid = share - > id . extid ;
2005-09-06 00:36:07 +04:00
sme - > share_access = ( uint32_t ) share - > share_access ;
sme - > access_mask = ( uint32_t ) share - > access_mask ;
sme - > open_time . tv_sec = share - > time . tv_sec ;
sme - > open_time . tv_usec = share - > time . tv_usec ;
sme - > file_id = ( uint32_t ) share - > share_file_id ;
sme - > pid = share - > pid ;
2005-09-14 02:23:59 +04:00
list_num + + ;
2005-09-06 00:36:07 +04:00
}
2005-09-14 02:23:59 +04:00
if ( list_num = = 0 ) {
2005-09-06 00:36:07 +04:00
free ( db_data . dptr ) ;
free ( list ) ;
return 0 ;
}
* p_delete_on_close = ld - > u . s . delete_on_close ;
* pp_list = list ;
2005-09-14 02:23:59 +04:00
free ( db_data . dptr ) ;
return list_num ;
2005-09-06 00:36:07 +04:00
}
/*
* Create an entry in the Samba share mode db .
*/
2005-12-13 01:07:36 +03:00
int smb_create_share_mode_entry_ex ( struct smbdb_ctx * db_ctx ,
2005-09-06 00:36:07 +04:00
uint64_t dev ,
uint64_t ino ,
2009-02-16 10:45:28 +03:00
uint64_t extid ,
2005-09-06 00:36:07 +04:00
const struct smb_share_mode_entry * new_entry ,
2005-12-13 01:07:36 +03:00
const char * sharepath , /* Must be absolute utf8 path. */
const char * filename ) /* Must be relative utf8 path. */
2005-09-06 00:36:07 +04:00
{
TDB_DATA db_data ;
2009-01-01 21:55:20 +03:00
struct locking_key lk ;
2009-02-16 10:45:28 +03:00
TDB_DATA locking_key = get_locking_key ( & lk , dev , ino , extid ) ;
2005-09-06 00:36:07 +04:00
int orig_num_share_modes = 0 ;
struct locking_data * ld = NULL ; /* internal samba db state. */
2005-09-30 21:13:37 +04:00
struct share_mode_entry * shares = NULL ;
2007-03-29 13:35:51 +04:00
uint8 * new_data_p = NULL ;
2005-09-06 00:36:07 +04:00
size_t new_data_size = 0 ;
db_data = tdb_fetch ( db_ctx - > smb_tdb , locking_key ) ;
if ( ! db_data . dptr ) {
/* We must create the entry. */
2007-03-29 13:35:51 +04:00
db_data . dptr = ( uint8 * ) malloc (
2007-03-30 02:12:28 +04:00
sizeof ( struct locking_data ) +
sizeof ( struct share_mode_entry ) +
2006-08-01 16:45:12 +04:00
strlen ( sharepath ) + 1 +
strlen ( filename ) + 1 ) ;
2005-09-06 00:36:07 +04:00
if ( ! db_data . dptr ) {
return - 1 ;
}
ld = ( struct locking_data * ) db_data . dptr ;
2006-02-04 09:31:04 +03:00
memset ( ld , ' \0 ' , sizeof ( struct locking_data ) ) ;
2005-09-06 00:36:07 +04:00
ld - > u . s . num_share_mode_entries = 1 ;
ld - > u . s . delete_on_close = 0 ;
2006-02-04 09:31:04 +03:00
ld - > u . s . delete_token_size = 0 ;
2007-03-30 02:12:28 +04:00
shares = ( struct share_mode_entry * ) ( db_data . dptr + sizeof ( struct locking_data ) ) ;
2005-09-06 00:36:07 +04:00
create_share_mode_entry ( shares , new_entry ) ;
2005-12-13 01:07:36 +03:00
2007-03-30 02:12:28 +04:00
memcpy ( db_data . dptr + sizeof ( struct locking_data ) + sizeof ( struct share_mode_entry ) ,
2005-12-13 01:07:36 +03:00
sharepath ,
strlen ( sharepath ) + 1 ) ;
2007-03-30 02:12:28 +04:00
memcpy ( db_data . dptr + sizeof ( struct locking_data ) + sizeof ( struct share_mode_entry ) +
2005-12-13 01:07:36 +03:00
strlen ( sharepath ) + 1 ,
2005-09-06 00:36:07 +04:00
filename ,
strlen ( filename ) + 1 ) ;
2007-03-30 02:12:28 +04:00
db_data . dsize = sizeof ( struct locking_data ) + sizeof ( struct share_mode_entry ) +
2005-12-13 01:07:36 +03:00
strlen ( sharepath ) + 1 +
strlen ( filename ) + 1 ;
2005-09-06 00:36:07 +04:00
if ( tdb_store ( db_ctx - > smb_tdb , locking_key , db_data , TDB_INSERT ) = = - 1 ) {
free ( db_data . dptr ) ;
return - 1 ;
}
free ( db_data . dptr ) ;
return 0 ;
}
/* Entry exists, we must add a new entry. */
2007-03-29 13:35:51 +04:00
new_data_p = ( uint8 * ) malloc (
2006-08-01 16:45:12 +04:00
db_data . dsize + sizeof ( struct share_mode_entry ) ) ;
2005-09-06 00:36:07 +04:00
if ( ! new_data_p ) {
free ( db_data . dptr ) ;
return - 1 ;
}
ld = ( struct locking_data * ) db_data . dptr ;
orig_num_share_modes = ld - > u . s . num_share_mode_entries ;
/* Copy the original data. */
2007-03-30 02:12:28 +04:00
memcpy ( new_data_p , db_data . dptr , sizeof ( struct locking_data ) + ( orig_num_share_modes * sizeof ( struct share_mode_entry ) ) ) ;
2005-09-06 00:36:07 +04:00
/* Add in the new share mode */
2007-03-30 02:12:28 +04:00
shares = ( struct share_mode_entry * ) ( new_data_p + sizeof ( struct locking_data ) +
( orig_num_share_modes * sizeof ( struct share_mode_entry ) ) ) ;
2005-09-14 02:23:59 +04:00
2005-09-06 00:36:07 +04:00
create_share_mode_entry ( shares , new_entry ) ;
ld = ( struct locking_data * ) new_data_p ;
ld - > u . s . num_share_mode_entries + + ;
2006-02-04 09:31:04 +03:00
/* Append the original delete_token and filenames. */
2007-03-30 02:12:28 +04:00
memcpy ( new_data_p + sizeof ( struct locking_data ) + ( ld - > u . s . num_share_mode_entries * sizeof ( struct share_mode_entry ) ) ,
db_data . dptr + sizeof ( struct locking_data ) + ( orig_num_share_modes * sizeof ( struct share_mode_entry ) ) ,
db_data . dsize - sizeof ( struct locking_data ) - ( orig_num_share_modes * sizeof ( struct share_mode_entry ) ) ) ;
2005-09-06 00:36:07 +04:00
2005-09-30 21:13:37 +04:00
new_data_size = db_data . dsize + sizeof ( struct share_mode_entry ) ;
2005-09-06 00:36:07 +04:00
free ( db_data . dptr ) ;
db_data . dptr = new_data_p ;
db_data . dsize = new_data_size ;
if ( tdb_store ( db_ctx - > smb_tdb , locking_key , db_data , TDB_REPLACE ) = = - 1 ) {
free ( db_data . dptr ) ;
return - 1 ;
}
free ( db_data . dptr ) ;
return 0 ;
}
2005-12-13 01:07:36 +03:00
/*
* Create an entry in the Samba share mode db . Original interface - doesn ' t
* Distinguish between share path and filename . Fudge this by using a
* sharepath of / and a relative filename of ( filename + 1 ) .
*/
int smb_create_share_mode_entry ( struct smbdb_ctx * db_ctx ,
uint64_t dev ,
uint64_t ino ,
2009-02-16 10:45:28 +03:00
uint64_t extid ,
2005-12-13 01:07:36 +03:00
const struct smb_share_mode_entry * new_entry ,
const char * filename ) /* Must be absolute utf8 path. */
{
if ( * filename ! = ' / ' ) {
abort ( ) ;
}
2009-02-16 10:45:28 +03:00
return smb_create_share_mode_entry_ex ( db_ctx , dev , ino , extid , new_entry ,
2005-12-13 01:07:36 +03:00
" / " , & filename [ 1 ] ) ;
}
2005-09-06 00:36:07 +04:00
int smb_delete_share_mode_entry ( struct smbdb_ctx * db_ctx ,
uint64_t dev ,
uint64_t ino ,
2009-02-16 10:45:28 +03:00
uint64_t extid ,
2005-09-06 00:36:07 +04:00
const struct smb_share_mode_entry * del_entry )
{
TDB_DATA db_data ;
2009-01-01 21:55:20 +03:00
struct locking_key lk ;
2009-02-16 10:45:28 +03:00
TDB_DATA locking_key = get_locking_key ( & lk , dev , ino , extid ) ;
2005-09-06 00:36:07 +04:00
int orig_num_share_modes = 0 ;
struct locking_data * ld = NULL ; /* internal samba db state. */
2005-09-30 21:13:37 +04:00
struct share_mode_entry * shares = NULL ;
2007-03-29 13:35:51 +04:00
uint8 * new_data_p = NULL ;
2006-02-04 09:31:04 +03:00
size_t remaining_size = 0 ;
2005-09-14 02:23:59 +04:00
size_t i , num_share_modes ;
2007-03-29 13:35:51 +04:00
const uint8 * remaining_ptr = NULL ;
2005-09-06 00:36:07 +04:00
db_data = tdb_fetch ( db_ctx - > smb_tdb , locking_key ) ;
if ( ! db_data . dptr ) {
return - 1 ; /* Error - missing entry ! */
}
ld = ( struct locking_data * ) db_data . dptr ;
orig_num_share_modes = ld - > u . s . num_share_mode_entries ;
2007-03-30 02:12:28 +04:00
shares = ( struct share_mode_entry * ) ( db_data . dptr + sizeof ( struct locking_data ) ) ;
2005-09-06 00:36:07 +04:00
if ( orig_num_share_modes = = 1 ) {
/* Only one entry - better be ours... */
if ( ! share_mode_entry_equal ( del_entry , shares ) ) {
/* Error ! We can't delete someone else's entry ! */
free ( db_data . dptr ) ;
return - 1 ;
}
/* It's ours - just remove the entire record. */
free ( db_data . dptr ) ;
return tdb_delete ( db_ctx - > smb_tdb , locking_key ) ;
}
/* More than one - allocate a new record minus the one we'll delete. */
2007-03-29 13:35:51 +04:00
new_data_p = ( uint8 * ) malloc (
2006-08-01 16:45:12 +04:00
db_data . dsize - sizeof ( struct share_mode_entry ) ) ;
2005-09-06 00:36:07 +04:00
if ( ! new_data_p ) {
free ( db_data . dptr ) ;
return - 1 ;
}
/* Copy the header. */
2007-03-30 02:12:28 +04:00
memcpy ( new_data_p , db_data . dptr , sizeof ( struct locking_data ) ) ;
2005-09-06 00:36:07 +04:00
2005-09-14 02:23:59 +04:00
num_share_modes = 0 ;
2005-09-06 00:36:07 +04:00
for ( i = 0 ; i < orig_num_share_modes ; i + + ) {
2005-09-30 21:13:37 +04:00
struct share_mode_entry * share = & shares [ i ] ;
2007-05-07 13:35:35 +04:00
struct server_id pid = share - > pid ;
2005-09-06 00:36:07 +04:00
/* Check this process really exists. */
2005-10-29 00:36:21 +04:00
if ( kill ( sharemodes_procid_to_pid ( & pid ) , 0 ) = = - 1 & & ( errno = = ESRCH ) ) {
2005-09-06 00:36:07 +04:00
continue ; /* No longer exists. */
}
if ( share_mode_entry_equal ( del_entry , share ) ) {
continue ; /* This is our delete taget. */
}
2007-03-30 02:12:28 +04:00
memcpy ( new_data_p + sizeof ( struct locking_data ) +
( num_share_modes * sizeof ( struct share_mode_entry ) ) ,
2005-09-30 21:13:37 +04:00
share , sizeof ( struct share_mode_entry ) ) ;
2005-09-14 02:23:59 +04:00
num_share_modes + + ;
2005-09-06 00:36:07 +04:00
}
2005-09-14 02:23:59 +04:00
if ( num_share_modes = = 0 ) {
2005-09-06 00:36:07 +04:00
/* None left after pruning. Delete record. */
free ( db_data . dptr ) ;
free ( new_data_p ) ;
return tdb_delete ( db_ctx - > smb_tdb , locking_key ) ;
}
2006-02-04 09:31:04 +03:00
/* Copy any delete token plus the terminating filenames. */
2007-03-30 02:12:28 +04:00
remaining_ptr = db_data . dptr + sizeof ( struct locking_data ) + ( orig_num_share_modes * sizeof ( struct share_mode_entry ) ) ;
2006-02-04 09:31:04 +03:00
remaining_size = db_data . dsize - ( remaining_ptr - db_data . dptr ) ;
2005-09-06 00:36:07 +04:00
2007-03-30 02:12:28 +04:00
memcpy ( new_data_p + sizeof ( struct locking_data ) + ( num_share_modes * sizeof ( struct share_mode_entry ) ) ,
2006-02-04 09:31:04 +03:00
remaining_ptr ,
remaining_size ) ;
2005-09-06 00:36:07 +04:00
free ( db_data . dptr ) ;
db_data . dptr = new_data_p ;
/* Re-save smaller record. */
ld = ( struct locking_data * ) db_data . dptr ;
2005-09-14 02:23:59 +04:00
ld - > u . s . num_share_mode_entries = num_share_modes ;
2005-09-06 00:36:07 +04:00
2007-03-30 02:12:28 +04:00
db_data . dsize = sizeof ( struct locking_data ) + ( num_share_modes * sizeof ( struct share_mode_entry ) ) + remaining_size ;
2005-09-06 00:36:07 +04:00
if ( tdb_store ( db_ctx - > smb_tdb , locking_key , db_data , TDB_REPLACE ) = = - 1 ) {
free ( db_data . dptr ) ;
return - 1 ;
}
free ( db_data . dptr ) ;
return 0 ;
}
int smb_change_share_mode_entry ( struct smbdb_ctx * db_ctx ,
uint64_t dev ,
uint64_t ino ,
2009-02-16 10:45:28 +03:00
uint64_t extid ,
2005-09-06 00:36:07 +04:00
const struct smb_share_mode_entry * set_entry ,
const struct smb_share_mode_entry * new_entry )
{
TDB_DATA db_data ;
2009-01-01 21:55:20 +03:00
struct locking_key lk ;
2009-02-16 10:45:28 +03:00
TDB_DATA locking_key = get_locking_key ( & lk , dev , ino , extid ) ;
2005-09-06 00:36:07 +04:00
int num_share_modes = 0 ;
struct locking_data * ld = NULL ; /* internal samba db state. */
2005-09-30 21:13:37 +04:00
struct share_mode_entry * shares = NULL ;
2005-09-06 00:36:07 +04:00
size_t i ;
int found_entry = 0 ;
db_data = tdb_fetch ( db_ctx - > smb_tdb , locking_key ) ;
if ( ! db_data . dptr ) {
return - 1 ; /* Error - missing entry ! */
}
ld = ( struct locking_data * ) db_data . dptr ;
num_share_modes = ld - > u . s . num_share_mode_entries ;
2007-03-30 02:12:28 +04:00
shares = ( struct share_mode_entry * ) ( db_data . dptr + sizeof ( struct locking_data ) ) ;
2005-09-06 00:36:07 +04:00
for ( i = 0 ; i < num_share_modes ; i + + ) {
2005-09-30 21:13:37 +04:00
struct share_mode_entry * share = & shares [ i ] ;
2007-05-07 13:35:35 +04:00
struct server_id pid = share - > pid ;
2005-09-06 00:36:07 +04:00
/* Check this process really exists. */
2005-10-29 00:36:21 +04:00
if ( kill ( sharemodes_procid_to_pid ( & pid ) , 0 ) = = - 1 & & ( errno = = ESRCH ) ) {
2005-09-06 00:36:07 +04:00
continue ; /* No longer exists. */
}
if ( share_mode_entry_equal ( set_entry , share ) ) {
create_share_mode_entry ( share , new_entry ) ;
2005-09-14 03:11:23 +04:00
found_entry = 1 ;
2005-09-06 00:36:07 +04:00
break ;
}
}
if ( ! found_entry ) {
free ( db_data . dptr ) ;
return - 1 ;
}
/* Save modified data. */
if ( tdb_store ( db_ctx - > smb_tdb , locking_key , db_data , TDB_REPLACE ) = = - 1 ) {
free ( db_data . dptr ) ;
return - 1 ;
}
free ( db_data . dptr ) ;
return 0 ;
}