feat: add DOS long-name alias support
This commit is contained in:
@@ -257,7 +257,7 @@ extern time_t nw_2_un_time(uint8 *d, uint8 *t);
|
||||
|
||||
extern void un_time_2_nw(time_t time, uint8 *d, int high_low);
|
||||
|
||||
extern void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp);
|
||||
extern void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp, int len);
|
||||
|
||||
extern int nw_add_trustee(int dir_handle, uint8 *data, int len,
|
||||
uint32 id, int trustee, int extended);
|
||||
|
||||
15
include/namedos.h
Normal file
15
include/namedos.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* namedos.h: DOS namespace helpers for mars_nwe
|
||||
*/
|
||||
#ifndef _NAMEDOS_H_
|
||||
#define _NAMEDOS_H_
|
||||
#if WITH_NAME_SPACE_CALLS
|
||||
|
||||
extern int dos_is_83_name(uint8 *name, int options);
|
||||
extern int build_dos_83_alias(int options, uint8 *parent_unix,
|
||||
uint8 *real_name, ino_t inode,
|
||||
uint8 *alias, int alias_len);
|
||||
extern void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp, int len);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -57,7 +57,7 @@ ELSE(ENABLE_INTERNAL_RIP_SAP)
|
||||
ENDIF(ENABLE_INTERNAL_RIP_SAP)
|
||||
|
||||
add_executable(nwserv nwserv.c net1.c tools.c ${EMUTLI} ${EMUTLI1} ${NWROUTE_0} )
|
||||
add_executable(nwconn nwconn.c net1.c tools.c connect.c namspace.c nwvolume.c nwfile.c unxfile.c nwqconn.c nameos2.c nwfname.c nwshare.c extpipe.c nwattrib.c trustee.c ${EMUTLI} )
|
||||
add_executable(nwconn nwconn.c net1.c tools.c connect.c namspace.c nwvolume.c nwfile.c unxfile.c nwqconn.c nameos2.c namedos.c nwfname.c nwshare.c extpipe.c nwattrib.c trustee.c ${EMUTLI} )
|
||||
add_executable(ncpserv ncpserv.c net1.c tools.c ${EMUTLI} )
|
||||
add_executable(nwclient nwclient.c net1.c tools.c ${EMUTLI} )
|
||||
add_executable(nwbind nwbind.c net1.c tools.c nwdbm.c nwcrypt.c unxlog.c sema.c nwqueue.c unxfile.c ${EMUTLI} )
|
||||
|
||||
211
src/connect.c
211
src/connect.c
@@ -58,8 +58,17 @@ static int act_umode_file=0;
|
||||
#include "nwfile.h"
|
||||
#include "nwconn.h"
|
||||
#include "namspace.h"
|
||||
#include "namedos.h"
|
||||
#include "connect.h"
|
||||
|
||||
/* connect.h may already be include-guarded through another header before
|
||||
* NW_VOL is visible, so keep this local forward declaration before the
|
||||
* first call in build_dir_name().
|
||||
*/
|
||||
void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp, int len);
|
||||
static void build_dos_attr_name(int volume, uint8 *path, char *unixname,
|
||||
struct stat *stb, uint8 *out, int out_len);
|
||||
|
||||
|
||||
typedef struct {
|
||||
dev_t dev; /* unix dev */
|
||||
@@ -107,6 +116,35 @@ static DIR_HANDLE dir_handles[MAX_DIRHANDLES];
|
||||
|
||||
static int anz_dirhandles=0;
|
||||
|
||||
|
||||
/* Last real directory entry found by the old DOS scan code.
|
||||
* Some callers rebuild unixname later from the synthetic DOS alias; keep the
|
||||
* real parent/name pair so the final attribute formatter can still generate
|
||||
* a collision-aware 8.3 alias for display.
|
||||
*/
|
||||
static int last_dos_alias_volume = -1;
|
||||
static ino_t last_dos_alias_inode = 0;
|
||||
static uint8 last_dos_alias_parent[300];
|
||||
static uint8 last_dos_alias_real[256];
|
||||
static uint8 last_dos_alias_alias[14];
|
||||
|
||||
static void remember_dos_alias_source(int volume, uint8 *parent, uint8 *real,
|
||||
ino_t inode)
|
||||
{
|
||||
last_dos_alias_volume = volume;
|
||||
last_dos_alias_inode = inode;
|
||||
strmaxcpy(last_dos_alias_parent, parent ? (char*)parent : "",
|
||||
sizeof(last_dos_alias_parent)-1);
|
||||
strmaxcpy(last_dos_alias_real, real ? (char*)real : "",
|
||||
sizeof(last_dos_alias_real)-1);
|
||||
last_dos_alias_alias[0] = '\0';
|
||||
if (parent && real) {
|
||||
build_dos_83_alias(get_volume_options(volume), parent, real, inode,
|
||||
last_dos_alias_alias, sizeof(last_dos_alias_alias));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *build_unix_name(NW_PATH *nwpath, int modus)
|
||||
/*
|
||||
* returns complete UNIX path
|
||||
@@ -597,19 +635,25 @@ static int func_search_entry(NW_PATH *nwpath, int attrib,
|
||||
if (dirbuff->d_ino) {
|
||||
uint8 *name=(uint8*)(dirbuff->d_name);
|
||||
uint8 dname[256];
|
||||
uint8 dosalias[14];
|
||||
xstrcpy(dname, name);
|
||||
unix2doscharset(dname);
|
||||
*kpath = '\0';
|
||||
build_dos_83_alias(soptions, (uint8*)xkpath, name,
|
||||
dirbuff->d_ino, dosalias, sizeof(dosalias));
|
||||
okflag = (name[0] != '.' &&
|
||||
( (!strcmp((char*)dname, (char*)entry))
|
||||
|| fn_dos_match(dname, entry, soptions)));
|
||||
( (!strcmp((char*)dosalias, (char*)entry))
|
||||
|| fn_dos_match(dosalias, entry, soptions)));
|
||||
if (okflag) {
|
||||
*kpath = '\0';
|
||||
strmaxcpy(kpath, (char*)name, sizeof(xkpath) - (int)(kpath-xkpath) -1 );
|
||||
if (!s_stat(xkpath, &(fs->statb), NULL)) {
|
||||
okflag = ( ( ( (fs->statb.st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10))
|
||||
|| ( ( (fs->statb.st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10)));
|
||||
if (okflag){
|
||||
xstrcpy(nwpath->fn, (char*)dname);
|
||||
*kpath = '\0';
|
||||
remember_dos_alias_source(volume, (uint8*)xkpath, name,
|
||||
fs->statb.st_ino);
|
||||
xstrcpy(nwpath->fn, (char*)dosalias);
|
||||
XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, fs->statb.st_mode));
|
||||
result = (*fs_func)(nwpath, fs);
|
||||
if (result < 0) break;
|
||||
@@ -678,13 +722,16 @@ static int get_dir_entry(NW_PATH *nwpath,
|
||||
if (dirbuff->d_ino) {
|
||||
uint8 *name=(uint8*)(dirbuff->d_name);
|
||||
uint8 dname[256];
|
||||
uint8 dosalias[14];
|
||||
xstrcpy(dname, name);
|
||||
unix2doscharset(dname);
|
||||
*kpath = '\0';
|
||||
build_dos_83_alias(soptions, (uint8*)xkpath, name,
|
||||
dirbuff->d_ino, dosalias, sizeof(dosalias));
|
||||
okflag = ((name[0] != '.' &&
|
||||
( (!strcmp((char*)dname, (char*)entry))
|
||||
|| fn_dos_match(dname, entry, soptions)))) ? 0 : -0xff;
|
||||
( (!strcmp((char*)dosalias, (char*)entry))
|
||||
|| fn_dos_match(dosalias, entry, soptions)))) ? 0 : -0xff;
|
||||
if (!okflag) {
|
||||
*kpath = '\0';
|
||||
strmaxcpy(kpath, (char*)name, sizeof(xkpath) - (int)(kpath-xkpath) -1);
|
||||
if (!s_stat(xkpath, statb, NULL)) {
|
||||
okflag = (( ( ( (statb->st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10))
|
||||
@@ -697,7 +744,11 @@ static int get_dir_entry(NW_PATH *nwpath,
|
||||
if (soptions & VOL_OPTION_IS_PIPE) {
|
||||
statb->st_size = 0x70000000|(statb->st_mtime&0xfffffff);
|
||||
}
|
||||
xstrcpy(nwpath->fn, (char*)dname);
|
||||
*kpath = '\0';
|
||||
remember_dos_alias_source(volume, (uint8*)xkpath, name,
|
||||
statb->st_ino);
|
||||
XDPRINTF((99,0,"DOSGETDIR parent='%s' real='%s' alias='%s' inode=%ld", xkpath, name, dosalias, (long)statb->st_ino));
|
||||
xstrcpy(nwpath->fn, (char*)dosalias);
|
||||
XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, statb->st_mode));
|
||||
break; /* ready */
|
||||
} else
|
||||
@@ -781,11 +832,14 @@ static int get_dh_entry(DIR_HANDLE *dh,
|
||||
if (dirbuff->d_ino) {
|
||||
uint8 *name=(uint8*)(dirbuff->d_name);
|
||||
uint8 dname[256];
|
||||
uint8 dosalias[14];
|
||||
xstrcpy(dname, name);
|
||||
unix2doscharset(dname);
|
||||
build_dos_83_alias(dh->vol_options, (uint8*)dh->unixname, name,
|
||||
dirbuff->d_ino, dosalias, sizeof(dosalias));
|
||||
okflag = (name[0] != '.' &&
|
||||
( (!strcmp((char*)dname, (char*)entry))
|
||||
|| fn_dos_match(dname, entry, dh->vol_options)));
|
||||
( (!strcmp((char*)dosalias, (char*)entry))
|
||||
|| fn_dos_match(dosalias, entry, dh->vol_options)));
|
||||
|
||||
if (okflag) {
|
||||
strmaxcpy(dh->kpath, (char*)name,
|
||||
@@ -805,7 +859,11 @@ static int get_dh_entry(DIR_HANDLE *dh,
|
||||
if (okflag){
|
||||
if (unixname)
|
||||
strmaxcpy(unixname, dh->unixname, size_unixname-1);
|
||||
strmaxcpy((char*)search, (char*)dname, size_search-1);
|
||||
*(dh->kpath) = '\0';
|
||||
remember_dos_alias_source(dh->volume, (uint8*)dh->unixname,
|
||||
name, statb->st_ino);
|
||||
XDPRINTF((99,0,"DOSDH parent='%s' real='%s' alias='%s' inode=%ld", dh->unixname, name, dosalias, (long)statb->st_ino));
|
||||
strmaxcpy((char*)search, (char*)dosalias, size_search-1);
|
||||
break; /* ready */
|
||||
}
|
||||
} else okflag = 0;
|
||||
@@ -1052,7 +1110,7 @@ static int build_dir_name(NW_PATH *nwpath, /* gets complete path */
|
||||
dos2unixcharset(pp);
|
||||
pp += offset;
|
||||
pathlen -= offset;
|
||||
mangle_dos_name(v, unixname, pp);
|
||||
mangle_dos_name(v, unixname, pp, sizeof(unixname) - (int)(pp - unixname));
|
||||
unix2doscharset(pp);
|
||||
XDPRINTF((5, 0, "Mangled DOS/unixname=%s", unixname));
|
||||
memcpy(ppp, pp, pathlen);
|
||||
@@ -1183,10 +1241,12 @@ time_t nw_2_un_time(uint8 *d, uint8 *t)
|
||||
static int get_file_attrib(NW_FILE_INFO *f, char *unixname, struct stat *stb,
|
||||
NW_PATH *nwpath)
|
||||
{
|
||||
uint8 spath[14];
|
||||
uint32 dwattrib;
|
||||
strncpy((char*)f->name, (char*)nwpath->fn, sizeof(f->name));
|
||||
f->attrib[0]=0; /* d->name could be too long */
|
||||
up_fn(f->name);
|
||||
build_dos_attr_name(nwpath->volume, nwpath->fn, unixname, stb,
|
||||
spath, sizeof(spath));
|
||||
memset(f->name, 0, sizeof(f->name));
|
||||
strncpy((char*)f->name, (char*)spath, sizeof(f->name)-1);
|
||||
|
||||
dwattrib = get_nw_attrib_dword(nwpath->volume, unixname, stb);
|
||||
U16_TO_16(dwattrib, f->attrib);
|
||||
@@ -1203,11 +1263,13 @@ static int get_file_attrib(NW_FILE_INFO *f, char *unixname, struct stat *stb,
|
||||
static int get_dir_attrib(NW_DIR_INFO *d, char *unixname, struct stat *stb,
|
||||
NW_PATH *nwpath)
|
||||
{
|
||||
uint8 spath[14];
|
||||
uint32 dwattrib;
|
||||
XDPRINTF((5,0, "get_dir_attrib of %s", conn_get_nwpath_name(nwpath)));
|
||||
strncpy((char*)d->name, (char*)nwpath->fn, sizeof(d->name));
|
||||
d->attrib[0]=0; /* d->name could be too long */
|
||||
up_fn(d->name);
|
||||
build_dos_attr_name(nwpath->volume, nwpath->fn, unixname, stb,
|
||||
spath, sizeof(spath));
|
||||
memset(d->name, 0, sizeof(d->name));
|
||||
strncpy((char*)d->name, (char*)spath, sizeof(d->name)-1);
|
||||
|
||||
dwattrib = get_nw_attrib_dword(nwpath->volume, unixname, stb);
|
||||
U16_TO_16(dwattrib, d->attrib);
|
||||
@@ -2385,9 +2447,44 @@ static int s_nw_scan_dir_info(int dir_handle,
|
||||
|
||||
XDPRINTF((5,0,"SCAN_DIR: von %s, found %s:", dh->unixname, dirname));
|
||||
if (++aktsequence == dirsequence) { /* actual found */
|
||||
uint8 dosalias[14];
|
||||
char parent[300];
|
||||
char *slash;
|
||||
uint8 *leaf = dirname;
|
||||
|
||||
U16_TO_BE16(aktsequence, subnr);
|
||||
up_fn(dirname);
|
||||
strncpy((char*)subname, (char*)dirname, 16);
|
||||
|
||||
/*
|
||||
* Do not trust dirname here. Some old DOS scan paths carry the
|
||||
* raw 8 byte directory name only, which collapses colliding long
|
||||
* directories to the same display name (LONG_DIR/LONG_DIR).
|
||||
* Rebuild the final directory info name from the real full unixname
|
||||
* returned by get_dh_entry(), where the long on-disk leaf is still
|
||||
* available.
|
||||
*/
|
||||
if (unixname[0]) {
|
||||
strmaxcpy(parent, unixname, sizeof(parent)-1);
|
||||
slash = strrchr(parent, '/');
|
||||
if (slash) {
|
||||
leaf = (uint8*)(slash+1);
|
||||
*slash = '\0';
|
||||
if (!*parent) strcpy(parent, "/");
|
||||
build_dos_83_alias(dh->vol_options, (uint8*)parent,
|
||||
leaf, stbuff.st_ino,
|
||||
dosalias, sizeof(dosalias));
|
||||
} else {
|
||||
build_dos_83_alias(dh->vol_options, NULL,
|
||||
leaf, stbuff.st_ino,
|
||||
dosalias, sizeof(dosalias));
|
||||
}
|
||||
} else {
|
||||
build_dos_83_alias(dh->vol_options, (uint8*)dh->unixname,
|
||||
dirname, stbuff.st_ino,
|
||||
dosalias, sizeof(dosalias));
|
||||
}
|
||||
|
||||
up_fn(dosalias);
|
||||
strncpy((char*)subname, (char*)dosalias, 16);
|
||||
U32_TO_BE32(get_file_owner(&stbuff), owner);
|
||||
un_date_2_nw(stbuff.st_mtime, subdatetime, 1);
|
||||
un_time_2_nw(stbuff.st_mtime, subdatetime+2, 1);
|
||||
@@ -2440,6 +2537,60 @@ int nw_scan_dir_info(int dir_handle, uint8 *data, int len, uint8 *subnr,
|
||||
|
||||
|
||||
|
||||
static void build_dos_attr_name(int volume, uint8 *path, char *unixname,
|
||||
struct stat *stb, uint8 *out, int out_len)
|
||||
{
|
||||
char parent[300];
|
||||
char *slash;
|
||||
uint8 *leaf = path;
|
||||
int options = get_volume_options(volume);
|
||||
|
||||
if (!out || out_len < 2) return;
|
||||
*out = '\0';
|
||||
|
||||
if (stb && volume == last_dos_alias_volume
|
||||
&& stb->st_ino == last_dos_alias_inode
|
||||
&& last_dos_alias_parent[0] && last_dos_alias_real[0]) {
|
||||
if (last_dos_alias_alias[0]) {
|
||||
strmaxcpy(out, last_dos_alias_alias, out_len-1);
|
||||
up_fn(out);
|
||||
} else {
|
||||
build_dos_83_alias(options, last_dos_alias_parent,
|
||||
last_dos_alias_real, stb->st_ino, out, out_len);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prefer the real unixname when it is available. Some namespace/DOS scan
|
||||
* paths pass an already synthesized 8.3 name in `path`; if we return that
|
||||
* blindly, colliding long directories can both be displayed as LONG_DIR.
|
||||
*/
|
||||
if (unixname && *unixname) {
|
||||
strmaxcpy(parent, unixname, sizeof(parent)-1);
|
||||
slash = strrchr(parent, '/');
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
if (*(slash+1)) leaf = (uint8*)(slash+1);
|
||||
if (!*parent) strcpy(parent, "/");
|
||||
build_dos_83_alias(options, (uint8*)parent,
|
||||
leaf, stb ? stb->st_ino : 0, out, out_len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback: keep a previously synthesized DOS alias only when there is no
|
||||
* reliable real unixname to rebuild from. */
|
||||
if (path && *path && dos_is_83_name(path, options)) {
|
||||
strmaxcpy(out, path, out_len-1);
|
||||
up_fn(out);
|
||||
return;
|
||||
}
|
||||
|
||||
build_dos_83_alias(options, NULL,
|
||||
leaf, stb ? stb->st_ino : 0, out, out_len);
|
||||
}
|
||||
|
||||
void get_dos_file_attrib(NW_DOS_FILE_INFO *f,
|
||||
struct stat *stb,
|
||||
int volume,
|
||||
@@ -2448,9 +2599,9 @@ void get_dos_file_attrib(NW_DOS_FILE_INFO *f,
|
||||
{
|
||||
uint8 spath[14];
|
||||
uint32 nw_owner=get_file_owner(stb);
|
||||
f->namlen=min(strlen((char*)path), 12);
|
||||
strmaxcpy(spath, path, 12);
|
||||
up_fn(spath);
|
||||
build_dos_attr_name(volume, path, unixname, stb, spath, sizeof(spath));
|
||||
XDPRINTF((99,0,"DOSFILEATTR path='%s' unix='%s' alias='%s' inode=%ld", path ? (char*)path : "", unixname ? unixname : "", spath, stb ? (long)stb->st_ino : 0L));
|
||||
f->namlen=min(strlen((char*)spath), 12);
|
||||
strncpy((char*)f->name, (char*)spath, f->namlen);
|
||||
U32_TO_32(get_nw_attrib_dword(volume, unixname, stb), f->attributes);
|
||||
U16_TO_16(tru_get_inherited_mask(volume, unixname, stb),
|
||||
@@ -2475,9 +2626,9 @@ void get_dos_dir_attrib(NW_DOS_DIR_INFO *f,
|
||||
char *unixname)
|
||||
{
|
||||
uint8 spath[14];
|
||||
f->namlen=min(strlen((char*)path), 12);
|
||||
strmaxcpy(spath, path, 12);
|
||||
up_fn(spath);
|
||||
build_dos_attr_name(volume, path, unixname, stb, spath, sizeof(spath));
|
||||
XDPRINTF((99,0,"DOSDIRATTR path='%s' unix='%s' alias='%s' inode=%ld", path ? (char*)path : "", unixname ? unixname : "", spath, stb ? (long)stb->st_ino : 0L));
|
||||
f->namlen=min(strlen((char*)spath), 12);
|
||||
strncpy((char*)f->name, (char*)spath, f->namlen);
|
||||
U32_TO_32(get_nw_attrib_dword(volume, unixname, stb),
|
||||
f->attributes);
|
||||
@@ -2679,13 +2830,7 @@ static int get_match(uint8 *unixname, uint8 *p)
|
||||
return(0);
|
||||
}
|
||||
|
||||
void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp)
|
||||
{
|
||||
struct stat stb;
|
||||
if (!s_stat(unixname, &stb, NULL)) /* path is ok I hope */
|
||||
return;
|
||||
get_match(unixname, pp-1);
|
||||
}
|
||||
/* DOS name mangling is provided by namedos.c. */
|
||||
|
||||
|
||||
int nw_add_trustee(int dir_handle, uint8 *data, int len,
|
||||
|
||||
396
src/namedos.c
Normal file
396
src/namedos.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/* namedos.c : NameSpace DOS Services, mars_nwe
|
||||
*
|
||||
* Adds DOS 8.3 alias generation/resolution for long filenames on DOS
|
||||
* namespace clients. This file was originally derived from nameos2.c,
|
||||
* but DOS needs synthetic aliases while OS/2 can address long names.
|
||||
*/
|
||||
|
||||
#include "net.h"
|
||||
#include <dirent.h>
|
||||
#include <utime.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#ifndef LINUX
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "nwfname.h"
|
||||
#include "nwvolume.h"
|
||||
#include "connect.h"
|
||||
#include "nwfile.h"
|
||||
#include "unxfile.h"
|
||||
#include "namedos.h"
|
||||
|
||||
#if WITH_NAME_SPACE_CALLS
|
||||
|
||||
#define MAX_NAME_DOS_CACHE 0
|
||||
|
||||
static int dos_is_alias_char(int c)
|
||||
{
|
||||
if (isalnum((unsigned char)c)) return(1);
|
||||
switch (c) {
|
||||
case '$': case '%': case '\'': case '-': case '_': case '@':
|
||||
case '~': case '`': case '!': case '(': case ')': case '{':
|
||||
case '}': case '^': case '#': case '&':
|
||||
return(1);
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int dos_alias_char(int c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z') c -= ('a' - 'A');
|
||||
if (dos_is_alias_char(c)) return(c);
|
||||
return('_');
|
||||
}
|
||||
|
||||
int dos_is_83_name(uint8 *name, int options)
|
||||
{
|
||||
uint8 *ss=name;
|
||||
int len=0;
|
||||
int pf=0;
|
||||
|
||||
if (!name || !*name) return(0);
|
||||
if (!strcmp((char*)name, ".") || !strcmp((char*)name, "..")) return(1);
|
||||
|
||||
for (; *ss; ss++){
|
||||
if (*ss == '.') {
|
||||
if (pf++) return(0); /* no second dot */
|
||||
if (!len) return(0); /* no empty base */
|
||||
len=0;
|
||||
} else {
|
||||
if (!dos_is_alias_char(*ss)) return(0);
|
||||
++len;
|
||||
if ((pf && len > 3) || len > 8) return(0);
|
||||
if (!(options & VOL_OPTION_IGNCASE)){
|
||||
if (options & VOL_OPTION_DOWNSHIFT){
|
||||
if (*ss >= 'A' && *ss <= 'Z') return(0);
|
||||
} else {
|
||||
if (*ss >= 'a' && *ss <= 'z') return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(len > 0);
|
||||
}
|
||||
|
||||
static void build_dos_83_raw(uint8 *real_name, uint8 *alias, int alias_len)
|
||||
{
|
||||
uint8 base[9];
|
||||
uint8 ext[4];
|
||||
uint8 *dot=NULL;
|
||||
uint8 *s;
|
||||
int bl=0, el=0;
|
||||
|
||||
memset(base, 0, sizeof(base));
|
||||
memset(ext, 0, sizeof(ext));
|
||||
|
||||
if (!real_name || !*real_name) {
|
||||
strmaxcpy(alias, "_", alias_len-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (real_name[0] != '.')
|
||||
dot=(uint8*)strrchr((char*)real_name, '.');
|
||||
|
||||
for (s=real_name; *s && s != dot; s++) {
|
||||
if (bl < 8) base[bl++] = (uint8)dos_alias_char(*s);
|
||||
}
|
||||
if (!bl) base[bl++] = '_';
|
||||
|
||||
if (dot) {
|
||||
for (s=dot+1; *s; s++) {
|
||||
if (el < 3) ext[el++] = (uint8)dos_alias_char(*s);
|
||||
}
|
||||
}
|
||||
|
||||
if (el)
|
||||
snprintf((char*)alias, alias_len, "%s.%s", base, ext);
|
||||
else
|
||||
snprintf((char*)alias, alias_len, "%s", base);
|
||||
}
|
||||
|
||||
static int alias_base_equal(uint8 *a, uint8 *b)
|
||||
{
|
||||
uint8 aa[14], bb[14];
|
||||
uint8 *pa, *pb;
|
||||
strmaxcpy(aa, a, sizeof(aa)-1);
|
||||
strmaxcpy(bb, b, sizeof(bb)-1);
|
||||
pa=(uint8*)strchr((char*)aa, '.');
|
||||
pb=(uint8*)strchr((char*)bb, '.');
|
||||
if (pa) *pa='\0';
|
||||
if (pb) *pb='\0';
|
||||
return(!strcmp((char*)aa, (char*)bb));
|
||||
}
|
||||
|
||||
static char dos_digit(int n)
|
||||
{
|
||||
n &= 0x0f;
|
||||
return((n < 10) ? ('0' + n) : ('A' + n - 10));
|
||||
}
|
||||
|
||||
static void apply_collision_number(uint8 *alias, int collision)
|
||||
{
|
||||
uint8 *dot=(uint8*)strchr((char*)alias, '.');
|
||||
uint8 ext[5];
|
||||
uint8 base[9];
|
||||
int bl;
|
||||
|
||||
memset(ext, 0, sizeof(ext));
|
||||
memset(base, 0, sizeof(base));
|
||||
if (dot) {
|
||||
strmaxcpy(ext, dot, sizeof(ext)-1);
|
||||
*dot='\0';
|
||||
}
|
||||
strmaxcpy(base, alias, sizeof(base)-1);
|
||||
bl=strlen((char*)base);
|
||||
if (bl >= 8) bl=7;
|
||||
base[bl++] = dos_digit(collision);
|
||||
base[bl] = '\0';
|
||||
snprintf((char*)alias, 14, "%s%s", base, ext);
|
||||
}
|
||||
|
||||
int build_dos_83_alias(int options, uint8 *parent_unix,
|
||||
uint8 *real_name, ino_t inode,
|
||||
uint8 *alias, int alias_len)
|
||||
{
|
||||
uint8 raw[14];
|
||||
int collisions=0;
|
||||
DIR *d;
|
||||
|
||||
(void)inode;
|
||||
|
||||
if (alias_len < 2) return(0);
|
||||
*alias='\0';
|
||||
|
||||
if (dos_is_83_name(real_name, options)) {
|
||||
strmaxcpy(alias, real_name, alias_len-1);
|
||||
up_fn(alias);
|
||||
return(strlen((char*)alias));
|
||||
}
|
||||
|
||||
build_dos_83_raw(real_name, raw, sizeof(raw));
|
||||
strmaxcpy(alias, raw, alias_len-1);
|
||||
|
||||
if (parent_unix && *parent_unix && NULL != (d=opendir((char*)parent_unix))) {
|
||||
struct dirent *de;
|
||||
while ((de=readdir(d)) != NULL) {
|
||||
uint8 other[14];
|
||||
if (!de->d_ino) continue;
|
||||
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
|
||||
if (!strcmp(de->d_name, (char*)real_name)) continue;
|
||||
build_dos_83_raw((uint8*)de->d_name, other, sizeof(other));
|
||||
if (!strcmp((char*)other, (char*)raw)) {
|
||||
if (strcmp(de->d_name, (char*)real_name) < 0)
|
||||
collisions++;
|
||||
}
|
||||
/* A real 8.3 name that equals the raw alias consumes that alias. */
|
||||
if (dos_is_83_name((uint8*)de->d_name, options)) {
|
||||
uint8 native[14];
|
||||
strmaxcpy(native, (uint8*)de->d_name, sizeof(native)-1);
|
||||
up_fn(native);
|
||||
if (!strcmp((char*)native, (char*)raw)) collisions++;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
if (collisions > 0) {
|
||||
strmaxcpy(alias, raw, alias_len-1);
|
||||
apply_collision_number(alias, collisions-1);
|
||||
}
|
||||
|
||||
up_fn(alias);
|
||||
return(strlen((char*)alias));
|
||||
}
|
||||
|
||||
static int dos_alias_match(uint8 *a, uint8 *b)
|
||||
{
|
||||
uint8 aa[14], bb[14];
|
||||
strmaxcpy(aa, a, sizeof(aa)-1);
|
||||
strmaxcpy(bb, b, sizeof(bb)-1);
|
||||
up_fn(aa);
|
||||
up_fn(bb);
|
||||
return(!strcmp((char*)aa, (char*)bb));
|
||||
}
|
||||
|
||||
void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp, int len)
|
||||
{
|
||||
uint8 wanted[14];
|
||||
uint8 rest[512];
|
||||
uint8 *slash;
|
||||
uint8 *parent_slash;
|
||||
DIR *d;
|
||||
|
||||
if (!vol || !unixname || !pp || !*pp) return;
|
||||
if (len <= 1) return;
|
||||
|
||||
slash=(uint8*)strchr((char*)pp, '/');
|
||||
memset(rest, 0, sizeof(rest));
|
||||
if (slash) {
|
||||
strmaxcpy(rest, slash, sizeof(rest)-1);
|
||||
*slash='\0';
|
||||
}
|
||||
|
||||
strmaxcpy(wanted, pp, sizeof(wanted)-1);
|
||||
up_fn(wanted);
|
||||
|
||||
parent_slash = (pp > unixname && *(pp-1) == '/') ? pp-1 : NULL;
|
||||
if (parent_slash) *parent_slash='\0';
|
||||
|
||||
d=opendir((char*)unixname);
|
||||
if (d) {
|
||||
struct dirent *de;
|
||||
while ((de=readdir(d)) != NULL) {
|
||||
uint8 alias[14];
|
||||
if (!de->d_ino) continue;
|
||||
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
|
||||
build_dos_83_alias(vol->options, unixname, (uint8*)de->d_name,
|
||||
de->d_ino, alias, sizeof(alias));
|
||||
if (dos_alias_match(alias, wanted)) {
|
||||
if (parent_slash) *parent_slash='/';
|
||||
snprintf((char*)pp, len, "%s%s", de->d_name, rest);
|
||||
closedir(d);
|
||||
if (*rest) {
|
||||
uint8 *next=(uint8*)strchr((char*)pp, '/');
|
||||
if (next && *(next+1))
|
||||
mangle_dos_name(vol, unixname, next+1, len - (int)((next+1) - pp));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
if (parent_slash) *parent_slash='/';
|
||||
if (slash) *slash='/';
|
||||
}
|
||||
|
||||
static inline int get_n_p(uint8 **p)
|
||||
{
|
||||
int pc=**p;
|
||||
(*p)++;
|
||||
if (pc == '\\') {
|
||||
pc=**p;
|
||||
(*p)++;
|
||||
} else if (pc == 255) {
|
||||
pc=**p;
|
||||
(*p)++;
|
||||
switch (pc) {
|
||||
case 0xaa :
|
||||
case '*' : return(3000); /* star */
|
||||
|
||||
case 0xae :
|
||||
case '.' : return(1000); /* point */
|
||||
|
||||
case 0xbf :
|
||||
case '?' : return(2000); /* ? */
|
||||
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
return(pc);
|
||||
}
|
||||
|
||||
static int ns_fn_dos_match(uint8 *s, uint8 *p, int soptions)
|
||||
/* OS/2 name matching routine */
|
||||
{
|
||||
int pc, sc;
|
||||
uint state = 0;
|
||||
int anf, ende;
|
||||
int not = 0;
|
||||
uint found = 0;
|
||||
while ( (pc = get_n_p(&p)) != 0) {
|
||||
if (!(soptions & VOL_OPTION_IGNCASE)) {
|
||||
if (soptions & VOL_OPTION_DOWNSHIFT){ /* only downshift chars */
|
||||
if (*s >= 'A' && *s <= 'Z') return(0);
|
||||
} else {
|
||||
if (*s >= 'a' && *s <= 'z') return(0);
|
||||
}
|
||||
}
|
||||
switch (state){
|
||||
case 0 :
|
||||
switch (pc) {
|
||||
case '.' :
|
||||
case 1000: if (*s && ('.' != *s++))
|
||||
return(0);
|
||||
break;
|
||||
|
||||
case '?' :
|
||||
case 2000: if (!*s) return(0);
|
||||
++s;
|
||||
break;
|
||||
|
||||
case '*' :
|
||||
case 3000: {
|
||||
uint8 *pp;
|
||||
int np;
|
||||
if (!*p) return(1); /* last star */
|
||||
while (*s) {
|
||||
if (ns_fn_dos_match(s, p, soptions) == 1) return(1);
|
||||
else if (*s=='.') {
|
||||
pp=p;
|
||||
if (!get_n_p(&p) || !get_n_p(&p))
|
||||
return(0);
|
||||
p=pp;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
pp=p;
|
||||
np=get_n_p(&p);
|
||||
p=pp;
|
||||
if (np == '.' || np == 1000)
|
||||
return(ns_fn_dos_match(s, p, soptions));
|
||||
}
|
||||
return(0);
|
||||
|
||||
case '[' : if ( (*p == '!') || (*p == '^') ){
|
||||
++p;
|
||||
not = 1;
|
||||
}
|
||||
state = 1;
|
||||
continue;
|
||||
|
||||
default : if (soptions & VOL_OPTION_IGNCASE) {
|
||||
if (!dfn_imatch(*s, pc))
|
||||
return(0);
|
||||
} else if (pc != *s) return(0);
|
||||
++s;
|
||||
break;
|
||||
|
||||
} /* switch */
|
||||
break;
|
||||
|
||||
case 1 : /* Bereich von Zeichen */
|
||||
sc = *s++;
|
||||
found = not;
|
||||
if (!sc) return(0);
|
||||
do {
|
||||
if (pc == '\\') pc = *(p++);
|
||||
if (!pc) return(0);
|
||||
anf = pc;
|
||||
if (*p == '-' && *(p+1) != ']'){
|
||||
ende = *(++p);
|
||||
p++;
|
||||
}
|
||||
else ende = anf;
|
||||
if (found == not) { /* only if not found */
|
||||
if (anf == sc || (anf <= sc && sc <= ende))
|
||||
found = !not;
|
||||
}
|
||||
} while ((pc = *(p++)) != ']');
|
||||
if (! found ) return(0);
|
||||
not = 0;
|
||||
found = 0;
|
||||
state = 0;
|
||||
break;
|
||||
|
||||
default : break;
|
||||
} /* switch */
|
||||
} /* while */
|
||||
if (*s=='.' && *(s+1)=='\0') return(1);
|
||||
return ( (*s) ? 0 : 1);
|
||||
}
|
||||
#endif
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "unxfile.h"
|
||||
#include "namspace.h"
|
||||
#include "nameos2.h"
|
||||
#include "namedos.h"
|
||||
|
||||
#if WITH_NAME_SPACE_CALLS
|
||||
|
||||
@@ -654,11 +655,12 @@ leave_build_nwpath:
|
||||
else
|
||||
up_fn(pp);
|
||||
|
||||
mangle_dos_name(v, unixname, pp);
|
||||
mangle_dos_name(v, unixname, pp, sizeof(unixname)-v->unixnamlen-npbeg);
|
||||
|
||||
if (nplen > 0) {
|
||||
unix2doscharset(pp);
|
||||
memcpy(nwpath->path+npbeg, pp, nplen);
|
||||
strmaxcpy(nwpath->path+npbeg, pp,
|
||||
sizeof(nwpath->path)-npbeg-1);
|
||||
}
|
||||
XDPRINTF((5,0, "Mangle DOS unixname='%s'", unixname));
|
||||
}
|
||||
@@ -908,46 +910,47 @@ static int build_base(int namespace,
|
||||
|
||||
static int build_dos_name(DIR_BASE_ENTRY *e, uint8 *fname, int size_fname)
|
||||
{
|
||||
uint8 *ss=e->nwpath.fn;
|
||||
int len=0;
|
||||
int pf=0;
|
||||
int is_ok=1;
|
||||
int options=get_volume_options(e->nwpath.volume);
|
||||
for (; *ss; ss++){
|
||||
if (*ss == '.') {
|
||||
if (pf++) { /* no 2. point */
|
||||
is_ok=0;
|
||||
break;
|
||||
}
|
||||
len=0;
|
||||
} else {
|
||||
++len;
|
||||
if ((pf && len > 3) || len > 8) {
|
||||
is_ok=0;
|
||||
break;
|
||||
}
|
||||
if (!(options & VOL_OPTION_IGNCASE)){
|
||||
if (options & VOL_OPTION_DOWNSHIFT){ /* only downshift chars */
|
||||
if (*ss >= 'A' && *ss <= 'Z') {
|
||||
is_ok=0;
|
||||
break;
|
||||
}
|
||||
} else { /* only upshift chars */
|
||||
if (*ss >= 'a' && *ss <= 'z') {
|
||||
is_ok=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_ok) {
|
||||
strmaxcpy(fname, e->nwpath.fn, size_fname-1);
|
||||
up_fn(fname);
|
||||
return(strlen(fname));
|
||||
char *parent_unix;
|
||||
int result;
|
||||
N_NW_PATH parent_path;
|
||||
int plen;
|
||||
|
||||
if (!e || !fname || size_fname < 2) return(0);
|
||||
|
||||
/*
|
||||
* e->nwpath.path contains the full entry path and e->nwpath.fn points to
|
||||
* the last component inside that buffer. alloc_nwpath2unix(..., 1|2)
|
||||
* only gives the parent if fn is behind path. For entries directly in the
|
||||
* volume root fn == path, so the old code accidentally used the entry
|
||||
* itself as parent. That made collision checks local to each directory and
|
||||
* both "long directory name one" and "long directory name two" became
|
||||
* LONG_DIR.
|
||||
*/
|
||||
memcpy(&parent_path, &(e->nwpath), sizeof(parent_path));
|
||||
if (e->nwpath.fn && e->nwpath.fn > e->nwpath.path) {
|
||||
plen = (int)(e->nwpath.fn - e->nwpath.path);
|
||||
if (plen > 0 && e->nwpath.path[plen-1] == '/') --plen;
|
||||
memcpy(parent_path.path, e->nwpath.path, plen);
|
||||
parent_path.path[plen] = '\0';
|
||||
} else {
|
||||
return(sprintf(fname, "%ld.___", (long)e->nwpath.statb.st_ino));
|
||||
parent_path.path[0] = '\0';
|
||||
}
|
||||
parent_path.fn = parent_path.path + strlen((char*)parent_path.path);
|
||||
|
||||
parent_unix = alloc_nwpath2unix(&parent_path, 2);
|
||||
result = build_dos_83_alias(get_volume_options(e->nwpath.volume),
|
||||
(uint8*)parent_unix,
|
||||
e->nwpath.fn,
|
||||
e->nwpath.statb.st_ino,
|
||||
fname,
|
||||
size_fname);
|
||||
XDPRINTF((99,0,"NSDOSNAME parent='%s' real='%s' alias='%s' inode=%ld",
|
||||
parent_unix ? parent_unix : "",
|
||||
e->nwpath.fn ? (char*)e->nwpath.fn : "",
|
||||
fname ? (char*)fname : "",
|
||||
(long)e->nwpath.statb.st_ino));
|
||||
xfree(parent_unix);
|
||||
return(result);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -1517,7 +1520,19 @@ static int search_match(struct dirent *dirbuff,
|
||||
XDPRINTF((8,0,"search_match, Name='%s' dname='%s'", name, dname));
|
||||
if (!inode_search) {
|
||||
if (namespace == NAME_DOS) {
|
||||
flag = (*name != '.' && fn_dos_match_old(dname, entry, vol_options));
|
||||
if (*name != '.') {
|
||||
uint8 dosalias[14];
|
||||
build_dos_83_alias(vol_options, ds->unixname, name,
|
||||
dirbuff->d_ino, dosalias, sizeof(dosalias));
|
||||
flag = fn_dos_match_old(dosalias, entry, vol_options);
|
||||
/*
|
||||
* Keep dname as the real on-disk name. get_add_new_entry()
|
||||
* appends dname to the parent and stats it; passing the synthetic
|
||||
* DOS alias here makes long-name matches fail with
|
||||
* "nw_search_file_dir:Cannot add entry". The alias is only for
|
||||
* matching and for the returned INFO_MSK_ENTRY_NAME.
|
||||
*/
|
||||
}
|
||||
} else if (namespace == NAME_OS2) {
|
||||
flag = (*name != '.' || (*(name+1) != '.' && *(name+1) != '\0' ))
|
||||
&& fn_os2_match(dname, entry, vol_options);
|
||||
|
||||
142
src/nwvolume.c
142
src/nwvolume.c
@@ -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");
|
||||
@@ -393,8 +476,27 @@ static int look_name_space_map(NW_VOL *v, DEV_NAMESPACE_MAP *dnm,
|
||||
int k=-1;
|
||||
while (++k < v->maps_count) {
|
||||
mp=v->dev_namespace_maps[k];
|
||||
if (mp->dev == dnm->dev && mp->namespace == dnm->namespace)
|
||||
return(k);
|
||||
if (mp->dev == dnm->dev) {
|
||||
/*
|
||||
* VOL_OPTION_ONE_DEV encodes handles as the raw 32-bit inode:
|
||||
*
|
||||
* handle = inode
|
||||
*
|
||||
* In that mode there is no room in the handle for the dev/namespace
|
||||
* map index. All namespaces on this one Unix device therefore have
|
||||
* to share the same map entry. Otherwise a volume with both 'o' and
|
||||
* 'O' set can map the DOS root entry, but later OS/2 namespace lookups
|
||||
* fail with:
|
||||
*
|
||||
* Cannot map inode=..., dev=..., namespace=4 to vol=... handle
|
||||
*
|
||||
* Non-ONE_DEV volumes keep the old behaviour and still distinguish
|
||||
* mappings by both device and namespace.
|
||||
*/
|
||||
if ((v->options & VOL_OPTION_ONE_DEV)
|
||||
|| mp->namespace == dnm->namespace)
|
||||
return(k);
|
||||
}
|
||||
}
|
||||
if (do_insert && v->maps_count < v->max_maps_count) {
|
||||
/* now do insert the new map */
|
||||
@@ -411,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);
|
||||
}
|
||||
|
||||
@@ -438,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));
|
||||
|
||||
Reference in New Issue
Block a user