dos mangle v16
All checks were successful
Source release / source-package (push) Successful in 54s

This commit is contained in:
Mario Fetka
2026-05-20 20:19:13 +02:00
parent beb4f83128
commit 74df6ddcf7

View File

@@ -64,6 +64,88 @@ char *path_trustees=NULL;
static int max_nw_vols=MAX_NW_VOLS;
/*
* Modern Linux filesystems can use inode numbers larger than 28 bits.
* The classic MARS_NWE handle format uses the upper 4 bits for the
* dev/namespace map index and the lower 28 bits for the inode. That
* breaks for volumes using multiple namespaces, for example DOS + OS2,
* when VOL_OPTION_ONE_DEV ('o') is not enabled.
*
* Keep the external 32-bit NetWare handle format, but map real Unix inode
* numbers to small pseudo inode numbers per volume/map entry. This allows
* OS2/NFS namespaces on large-inode filesystems without requiring the
* small 'o' ONE_DEV option.
*
* VOL_OPTION_ONE_DEV keeps its old direct 32-bit inode behaviour.
*/
typedef struct inode_handle_map_s {
int volume;
int map_entry;
ino_t inode;
uint32 handle_inode;
struct inode_handle_map_s *next;
} INODE_HANDLE_MAP;
static INODE_HANDLE_MAP *inode_handle_maps = NULL;
static uint32 next_handle_inode = 1;
static void free_inode_handle_maps(void)
{
INODE_HANDLE_MAP *m = inode_handle_maps;
while (m) {
INODE_HANDLE_MAP *n = m->next;
xfree(m);
m = n;
}
inode_handle_maps = NULL;
next_handle_inode = 1;
}
static uint32 inode_to_handle_inode(int volume, int map_entry, ino_t inode)
{
INODE_HANDLE_MAP *m;
for (m = inode_handle_maps; m; m = m->next) {
if (m->volume == volume && m->map_entry == map_entry && m->inode == inode)
return(m->handle_inode);
}
if (next_handle_inode > 0x0fffffff) {
XDPRINTF((1,0,
"No free pseudo inode handle for vol=%d map=%d inode=%ld",
volume, map_entry, (long)inode));
return(0);
}
m = (INODE_HANDLE_MAP*)xcmalloc(sizeof(INODE_HANDLE_MAP));
m->volume = volume;
m->map_entry = map_entry;
m->inode = inode;
m->handle_inode = next_handle_inode++;
m->next = inode_handle_maps;
inode_handle_maps = m;
XDPRINTF((99,0,
"Pseudo inode map vol=%d map=%d inode=%ld to pseudo=0x%x",
volume, map_entry, (long)inode, m->handle_inode));
return(m->handle_inode);
}
static ino_t handle_inode_to_inode(int volume, int map_entry, uint32 handle_inode)
{
INODE_HANDLE_MAP *m;
for (m = inode_handle_maps; m; m = m->next) {
if (m->volume == volume && m->map_entry == map_entry
&& m->handle_inode == handle_inode)
return(m->inode);
}
/* Compatibility fallback for old/direct handles. */
return((ino_t)handle_inode);
}
static void free_vol_trustee(NW_VOL *vol)
{
if (vol) {
@@ -143,6 +225,7 @@ void nw_init_volumes(FILE *f)
}
rewind(f);
used_nw_volumes = 0;
free_inode_handle_maps();
loaded_namespaces = 0;
new_str(path_vol_inodes_cache, "/var/spool/nwserv/.volcache");
new_str(path_attributes, "/var/nwserv/attrib");
@@ -430,20 +513,31 @@ uint32 nw_vol_inode_to_handle(int volume, ino_t inode,
{
if (volume > -1 && volume < used_nw_volumes) {
NW_VOL *v= &(nw_volumes[volume]);
if (inode > 0 && inode <= v->high_inode) {
if (inode > 0) {
int result = look_name_space_map(v, dnm, 1);
if (result > -1) {
uint32 handle = (v->options & VOL_OPTION_ONE_DEV)
? (uint32)inode
: (((uint32)result) << 28) | (uint32) inode;
XDPRINTF((3,0, "Handle map inode=%d, dev=%d, namespace=%d to handle 0x%x",
inode, dnm->dev, dnm->namespace, handle));
uint32 handle;
if (v->options & VOL_OPTION_ONE_DEV) {
if (inode > v->high_inode)
goto cannot_map;
handle = (uint32)inode;
} else {
uint32 handle_inode = inode_to_handle_inode(volume, result, inode);
if (!handle_inode)
goto cannot_map;
handle = (((uint32)result) << 28) | handle_inode;
}
XDPRINTF((3,0, "Handle map inode=%ld, dev=%d, namespace=%d to handle 0x%x",
(long)inode, dnm->dev, dnm->namespace, handle));
return(handle);
}
}
}
XDPRINTF((1,0, "Cannot map inode=%d, dev=%d, namespace=%d to vol=%d handle",
inode, dnm->dev, dnm->namespace, volume));
cannot_map:
XDPRINTF((1,0, "Cannot map inode=%ld, dev=%d, namespace=%d to vol=%d handle",
(long)inode, dnm->dev, dnm->namespace, volume));
return(0L);
}
@@ -457,13 +551,16 @@ ino_t nw_vol_handle_to_inode(int volume, uint32 handle,
? 0
: (int) ((handle >> 28) & 0xF);
if (entry > -1 && entry < v->maps_count) {
ino_t inode = (v->options & VOL_OPTION_ONE_DEV)
? (ino_t)(handle & v->high_inode)
: handle_inode_to_inode(volume, entry, handle & v->high_inode);
if (dnm) memcpy(dnm, v->dev_namespace_maps[entry],
sizeof(DEV_NAMESPACE_MAP));
XDPRINTF((3, 0, "vol=%d, handle=0x%x to ino=%d, dev=%d, namespace=%d",
volume, handle, (int)(handle & v->high_inode),
XDPRINTF((3, 0, "vol=%d, handle=0x%x to ino=%ld, dev=%d, namespace=%d",
volume, handle, (long)inode,
v->dev_namespace_maps[entry]->dev,
v->dev_namespace_maps[entry]->namespace));
return((ino_t) (handle & v->high_inode));
return(inode);
}
}
XDPRINTF((1, 0, "Can't vol=%d, handle=0x%x to inode", volume, handle));