274 lines
6.6 KiB
C
274 lines
6.6 KiB
C
/*
|
|
* Copyright 2000-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include "reiserfs/libreiserfs.h"
|
|
#include "misc/unaligned.h"
|
|
|
|
const reiserfs_key_t root_dir_key =
|
|
{cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID),
|
|
cpu_to_le32(REISERFS_ROOT_OBJECTID),
|
|
{{0, 0},}};
|
|
|
|
const reiserfs_key_t parent_root_dir_key = {
|
|
0, cpu_to_le32(REISERFS_ROOT_PARENT_OBJECTID),
|
|
{{0, 0},}};
|
|
|
|
reiserfs_key_t lost_found_dir_key =
|
|
{0, 0, {{0, 0}, }};
|
|
|
|
/* Minimal possible key. It is never in the tree. */
|
|
const reiserfs_key_t MIN_KEY = {0, 0, {{0, 0},}};
|
|
|
|
/* Maximal possible key. It is never in the tree. */
|
|
const reiserfs_key_t MAX_KEY =
|
|
{0xffffffff, 0xffffffff,
|
|
{{0xffffffff, 0xffffffff},}};
|
|
|
|
void reiserfs_key_copy (reiserfs_key_t * to, const reiserfs_key_t * from) {
|
|
memcpy (to, from, REISERFS_KEY_SIZE);
|
|
}
|
|
|
|
void reiserfs_key_copy2 (reiserfs_key_t * to, const reiserfs_key_t * from) {
|
|
memcpy (to, from, REISERFS_KEY_SHSIZE);
|
|
}
|
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
# define get_key_offset_v2(key) (__u64)((key->u.k2_offset_v2.k_offset))
|
|
# define set_key_offset_v2(key,val) (void)(key->u.k2_offset_v2.k_offset = (val))
|
|
# define get_key_type_v2(key) (__u16)((key->u.k2_offset_v2.k_type))
|
|
# define set_key_type_v2(key,val) (void)(key->u.k2_offset_v2.k_type = (val))
|
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
typedef union {
|
|
struct offset_v2 offset_v2;
|
|
__u64 linear;
|
|
} __attribute__ ((__packed__)) offset_v2_esafe_overlay;
|
|
|
|
static inline __u64 get_key_offset_v2 (const reiserfs_key_t *key)
|
|
{
|
|
offset_v2_esafe_overlay tmp =
|
|
*(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2));
|
|
tmp.linear = le64_to_cpu( tmp.linear );
|
|
return tmp.offset_v2.k_offset;
|
|
}
|
|
|
|
static inline __u32 get_key_type_v2 (const reiserfs_key_t *key)
|
|
{
|
|
offset_v2_esafe_overlay tmp =
|
|
*(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2));
|
|
tmp.linear = le64_to_cpu( tmp.linear );
|
|
return tmp.offset_v2.k_type;
|
|
}
|
|
|
|
static inline void set_key_offset_v2 (reiserfs_key_t *key, __u64 offset)
|
|
{
|
|
offset_v2_esafe_overlay *tmp =
|
|
(offset_v2_esafe_overlay *)(&(key->u.k2_offset_v2));
|
|
tmp->linear = le64_to_cpu(tmp->linear);
|
|
tmp->offset_v2.k_offset = offset;
|
|
tmp->linear = cpu_to_le64(tmp->linear);
|
|
}
|
|
|
|
static inline void set_key_type_v2 (reiserfs_key_t *key, __u32 type)
|
|
{
|
|
offset_v2_esafe_overlay *tmp =
|
|
(offset_v2_esafe_overlay *)(&(key->u.k2_offset_v2));
|
|
if (type > 15)
|
|
reiserfs_panic ("set_key_type_v2: type is too big %d", type);
|
|
|
|
tmp->linear = le64_to_cpu(tmp->linear);
|
|
tmp->offset_v2.k_type = type;
|
|
tmp->linear = cpu_to_le64(tmp->linear);
|
|
}
|
|
#else
|
|
# error "nuxi/pdp-endian archs are not supported"
|
|
#endif
|
|
|
|
static inline int is_key_format_1 (int type) {
|
|
return ( (type == 0 || type == 15) ? 1 : 0);
|
|
}
|
|
|
|
/* old keys (on i386) have k_offset_v2.k_type == 15 (direct and
|
|
extent) or == 0 (dir items and stat data) */
|
|
|
|
/* */
|
|
int reiserfs_key_format (const reiserfs_key_t * key)
|
|
{
|
|
int type;
|
|
|
|
type = get_key_type_v2 (key);
|
|
|
|
if (is_key_format_1 (type))
|
|
return KEY_FORMAT_1;
|
|
|
|
return KEY_FORMAT_2;
|
|
}
|
|
|
|
|
|
unsigned long long reiserfs_key_get_off (const reiserfs_key_t * key) {
|
|
if (reiserfs_key_format (key) == KEY_FORMAT_1)
|
|
return reiserfs_key_get_off1 (key);
|
|
|
|
return get_key_offset_v2 (key);
|
|
}
|
|
|
|
|
|
static int uniqueness2type (__u32 uniqueness) {
|
|
switch (uniqueness) {
|
|
case UNI_SD: return TYPE_STAT_DATA;
|
|
case UNI_EXT: return TYPE_EXTENT;
|
|
case UNI_DIRECT: return TYPE_DIRECT;
|
|
case UNI_DE: return TYPE_DIRENTRY;
|
|
}
|
|
return TYPE_UNKNOWN;
|
|
}
|
|
|
|
|
|
static __u32 type2uniqueness (int type) {
|
|
switch (type) {
|
|
case TYPE_STAT_DATA: return UNI_SD;
|
|
case TYPE_EXTENT: return UNI_EXT;
|
|
case TYPE_DIRECT: return UNI_DIRECT;
|
|
case TYPE_DIRENTRY: return UNI_DE;
|
|
}
|
|
return UNI_UNKN;
|
|
}
|
|
|
|
|
|
int reiserfs_key_get_type (const reiserfs_key_t * key)
|
|
{
|
|
int type_v2 = get_key_type_v2 (key);
|
|
|
|
if (is_key_format_1 (type_v2))
|
|
return uniqueness2type (reiserfs_key_get_uni (key));
|
|
|
|
return type_v2;
|
|
}
|
|
|
|
char *key_type_name[TYPE_UNKNOWN + 1] = {
|
|
[TYPE_STAT_DATA] = "SD",
|
|
[TYPE_EXTENT] = "EXT",
|
|
[TYPE_DIRECT] = "DRCT",
|
|
[TYPE_DIRENTRY] = "DIR",
|
|
[TYPE_UNKNOWN] = "???"
|
|
};
|
|
|
|
char * reiserfs_key_name (const reiserfs_key_t * key)
|
|
{
|
|
__u32 type = reiserfs_key_get_type (key);
|
|
return key_type_name[type <= TYPE_DIRENTRY ? type : TYPE_UNKNOWN];
|
|
}
|
|
|
|
/* this sets key format as well as type of item key belongs to */
|
|
void reiserfs_key_set_type (int format, reiserfs_key_t * key, int type)
|
|
{
|
|
if (format == KEY_FORMAT_1)
|
|
reiserfs_key_set_uni (key, type2uniqueness (type));
|
|
else
|
|
set_key_type_v2 (key, type);
|
|
}
|
|
|
|
|
|
void reiserfs_key_set_off (int format, reiserfs_key_t * key,
|
|
unsigned long long offset)
|
|
{
|
|
if (format == KEY_FORMAT_1)
|
|
reiserfs_key_set_off1 (key, offset);
|
|
else
|
|
set_key_offset_v2 (key, offset);
|
|
|
|
}
|
|
|
|
/* Set secondary fields. */
|
|
void reiserfs_key_set_sec (int format, reiserfs_key_t * key,
|
|
unsigned long long offset, int type)
|
|
{
|
|
reiserfs_key_set_type (format, key, type);
|
|
reiserfs_key_set_off (format, key, offset);
|
|
}
|
|
|
|
/*
|
|
Compare keys using REISERFS_KEY_SHORT_LEN fields.
|
|
Returns: -1 if key1 < key2
|
|
0 if key1 = key2
|
|
1 if key1 > key2
|
|
*/
|
|
|
|
int reiserfs_key_comp2 (const void * k1, const void * k2)
|
|
{
|
|
int n_key_length = REISERFS_KEY_SHORT_LEN;
|
|
__u32 * p_s_key1 = (__u32 *)k1;
|
|
__u32 * p_s_key2 = (__u32 *)k2;
|
|
__u32 u1, u2;
|
|
|
|
for( ; n_key_length--; ++p_s_key1, ++p_s_key2 ) {
|
|
u1 = d32_get(p_s_key1, 0) ;
|
|
u2 = d32_get(p_s_key2, 0) ;
|
|
if ( u1 < u2 )
|
|
return -1;
|
|
if ( u1 > u2 )
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int reiserfs_key_comp3 (const void * p1, const void * p2)
|
|
{
|
|
int retval;
|
|
const reiserfs_key_t * k1 = p1;
|
|
const reiserfs_key_t * k2 = p2;
|
|
unsigned long long off1, off2;
|
|
|
|
retval = reiserfs_key_comp2 (k1, k2);
|
|
if (retval)
|
|
return retval;
|
|
off1 = reiserfs_key_get_off(k1) ;
|
|
off2 = reiserfs_key_get_off(k2) ;
|
|
if (off1 < off2)
|
|
return -1;
|
|
|
|
if (off1 > off2)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
Compare keys using all 4 key fields.
|
|
Returns: -1 if key1 < key2
|
|
0 if key1 = key2
|
|
1 if key1 > key2
|
|
*/
|
|
int reiserfs_key_comp (const void * p1, const void * p2)
|
|
{
|
|
int retval;
|
|
const reiserfs_key_t * k1 = p1;
|
|
const reiserfs_key_t * k2 = p2;
|
|
__u32 u1, u2;
|
|
|
|
retval = reiserfs_key_comp3 (k1, k2);
|
|
if (retval)
|
|
return retval;
|
|
|
|
u1 = reiserfs_key_get_type (k1);
|
|
u2 = reiserfs_key_get_type (k2);
|
|
|
|
if (u1 < u2)
|
|
return -1;
|
|
|
|
if (u1 > u2)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|