2012-10-29 19:35:49 +04:00
/*
2007-05-29 13:30:34 +04:00
Unix SMB / CIFS implementation .
file_id structure handling
Copyright ( C ) Andrew Tridgell 2007
2012-10-29 19:35:49 +04:00
2007-05-29 13:30:34 +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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2007-05-29 13:30:34 +04:00
( at your option ) any later version .
2012-10-29 19:35:49 +04:00
2007-05-29 13:30:34 +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 .
2012-10-29 19:35:49 +04:00
2007-05-29 13:30:34 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2007-05-29 13:30:34 +04:00
*/
# include "includes.h"
2012-04-16 09:34:40 +04:00
# include "lib/file_id.h"
2007-05-29 13:30:34 +04:00
/*
return True if two file_id structures are equal
*/
2007-10-19 04:40:25 +04:00
bool file_id_equal ( const struct file_id * id1 , const struct file_id * id2 )
2007-05-29 13:30:34 +04:00
{
2009-02-16 10:45:28 +03:00
return id1 - > inode = = id2 - > inode & & id1 - > devid = = id2 - > devid & &
id1 - > extid = = id2 - > extid ;
2007-05-29 13:30:34 +04:00
}
/*
2012-04-16 09:36:15 +04:00
a static - like ( on talloc_tos ( ) ) string for a file_id structure
2007-05-29 13:30:34 +04:00
*/
2007-09-10 14:56:07 +04:00
const char * file_id_string_tos ( const struct file_id * id )
2007-05-29 13:30:34 +04:00
{
2012-10-29 19:41:15 +04:00
return file_id_string ( talloc_tos ( ) , id ) ;
2007-05-29 13:30:34 +04:00
}
2012-04-16 09:36:15 +04:00
/*
an allocated string for a file_id structure
*/
const char * file_id_string ( TALLOC_CTX * mem_ctx , const struct file_id * id )
{
char * result = talloc_asprintf ( mem_ctx , " %llx:%llx:%llx " ,
( unsigned long long ) id - > devid ,
( unsigned long long ) id - > inode ,
( unsigned long long ) id - > extid ) ;
SMB_ASSERT ( result ! = NULL ) ;
return result ;
}
2007-05-29 13:30:34 +04:00
/*
2009-02-16 10:45:28 +03:00
push a 16 byte version of a file id into a buffer . This ignores the extid
and is needed when dev / inodes are stored in persistent storage ( tdbs ) .
2007-05-29 13:30:34 +04:00
*/
void push_file_id_16 ( char * buf , const struct file_id * id )
{
SIVAL ( buf , 0 , id - > devid & 0xFFFFFFFF ) ;
SIVAL ( buf , 4 , id - > devid > > 32 ) ;
SIVAL ( buf , 8 , id - > inode & 0xFFFFFFFF ) ;
SIVAL ( buf , 12 , id - > inode > > 32 ) ;
}
/*
2009-02-16 10:45:28 +03:00
push a 24 byte version of a file id into a buffer
2007-05-29 13:30:34 +04:00
*/
2009-02-16 10:45:28 +03:00
void push_file_id_24 ( char * buf , const struct file_id * id )
{
SIVAL ( buf , 0 , id - > devid & 0xFFFFFFFF ) ;
SIVAL ( buf , 4 , id - > devid > > 32 ) ;
SIVAL ( buf , 8 , id - > inode & 0xFFFFFFFF ) ;
SIVAL ( buf , 12 , id - > inode > > 32 ) ;
SIVAL ( buf , 16 , id - > extid & 0xFFFFFFFF ) ;
SIVAL ( buf , 20 , id - > extid > > 32 ) ;
}
/*
pull a 24 byte version of a file id from a buffer
*/
2013-09-03 15:51:48 +04:00
void pull_file_id_24 ( const char * buf , struct file_id * id )
2007-05-29 13:30:34 +04:00
{
ZERO_STRUCTP ( id ) ;
id - > devid = IVAL ( buf , 0 ) ;
id - > devid | = ( ( uint64_t ) IVAL ( buf , 4 ) ) < < 32 ;
id - > inode = IVAL ( buf , 8 ) ;
id - > inode | = ( ( uint64_t ) IVAL ( buf , 12 ) ) < < 32 ;
2009-02-16 10:45:28 +03:00
id - > extid = IVAL ( buf , 16 ) ;
id - > extid | = ( ( uint64_t ) IVAL ( buf , 20 ) ) < < 32 ;
2007-05-29 13:30:34 +04:00
}
2019-06-25 15:13:28 +03:00
uint64_t make_file_id_from_itime ( SMB_STRUCT_STAT * st )
{
struct timespec itime = st - > st_ex_itime ;
ino_t ino = st - > st_ex_ino ;
uint64_t file_id_low ;
uint64_t file_id ;
if ( st - > st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME ) {
return ino ;
}
file_id_low = itime . tv_nsec ;
if ( file_id_low = = 0 ) {
/*
* This could be by coincidence , but more likely the filesystem
* is only giving us seconds granularity . We need more fine
* grained granularity for the File - ID , so combine with the
* inode number .
*/
file_id_low = ino & ( ( 1 < < 30 ) - 1 ) ;
}
/*
* Set the high bit so ideally File - IDs based on inode numbers and
* File - IDs based on Birth Time use disjoint ranges , given inodes never
* have the high bit set .
*/
file_id = ( ( uint64_t ) 1 ) < < 63 ;
file_id | = ( uint64_t ) itime . tv_sec < < 30 ;
file_id | = file_id_low ;
return file_id ;
}