This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
* namedos.h: 08-Aug-96
|
||||
*
|
||||
* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
|
||||
* 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);
|
||||
extern int fn_dos_match(uint8 *s, uint8 *p, int soptions);
|
||||
|
||||
|
||||
343
src/namedos.c
343
src/namedos.c
@@ -1,24 +1,16 @@
|
||||
/* nameos2.c 14-May-97 : NameSpace DOS Services, mars_nwe */
|
||||
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
|
||||
/* namedos.c : NameSpace DOS Services, mars_nwe
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* 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
|
||||
@@ -34,133 +26,246 @@
|
||||
|
||||
#define MAX_NAME_DOS_CACHE 0
|
||||
|
||||
#if MAX_NAME_DOS_CACHE
|
||||
typedef struct {
|
||||
uint8 *cache[MAX_NAME_DOS_CACHE];
|
||||
} DOSBUF;
|
||||
|
||||
static void init_dosbuf(NW_VOL *vol)
|
||||
static int dos_is_alias_char(int c)
|
||||
{
|
||||
vol->dosbuf = xcmalloc(sizeof(DOSBUF));
|
||||
}
|
||||
|
||||
static int vgl_name(uint8 *s, uint8 *p)
|
||||
{
|
||||
int hit=0;
|
||||
if (!s) return(0);
|
||||
for (; *s && *p; s++,p++) {
|
||||
if (*s == *p) {
|
||||
if (*s == '/')
|
||||
++hit;
|
||||
} else if ((!isalpha(*p)) || (!isalpha(*s))
|
||||
|| (*p | 0x20) != (*s | 0x20)) {
|
||||
return(hit);
|
||||
}
|
||||
}
|
||||
return((*s == *p) ? -1 : hit);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int my_match(uint8 *s, uint8 *p)
|
||||
{
|
||||
int len=0;
|
||||
for (; *s && *p; s++,p++) {
|
||||
if (!ufn_imatch(*s, *p))
|
||||
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);
|
||||
++len;
|
||||
}
|
||||
return( ((!*s) && (*p=='/' || *p == '\0')) ? len : 0);
|
||||
}
|
||||
|
||||
static int get_match(uint8 *unixname, uint8 *p)
|
||||
static int dos_alias_char(int c)
|
||||
{
|
||||
DIR *d;
|
||||
if (!p || !*p) return(1);
|
||||
*p = '\0';
|
||||
if (NULL != (d=opendir(unixname))) {
|
||||
struct dirent *dirbuff;
|
||||
XDPRINTF((10, 0, "opendir OK unixname='%s' p='%s'", unixname, p+1));
|
||||
*p = '/';
|
||||
while ((dirbuff = readdir(d)) != (struct dirent*)NULL){
|
||||
int len;
|
||||
if (dirbuff->d_ino) {
|
||||
XDPRINTF((10, 0, "get match found d_name='%s'", dirbuff->d_name));
|
||||
if (0 != (len=my_match(dirbuff->d_name, p+1))) {
|
||||
memcpy(p+1, dirbuff->d_name, len);
|
||||
XDPRINTF((10, 0, "get match, match OK"));
|
||||
closedir(d);
|
||||
return(get_match(unixname, p+1+len));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
} else {
|
||||
XDPRINTF((2, 0, "dos get_match opendir failed unixname='%s'", unixname));
|
||||
*p='/';
|
||||
}
|
||||
return(0);
|
||||
return(len > 0);
|
||||
}
|
||||
|
||||
#if MAX_NAME_DOS_CACHE
|
||||
static int get_name(uint8 *s, uint8 *unixname, int hit, uint8 *p)
|
||||
static void build_dos_83_raw(uint8 *real_name, uint8 *alias, int alias_len)
|
||||
{
|
||||
if (hit && s) {
|
||||
for (; *s && *p; s++,p++) {
|
||||
if (*s=='/') {
|
||||
if (!--hit) break;
|
||||
} else *p=*s;
|
||||
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);
|
||||
}
|
||||
} else
|
||||
--p; /* to get last '/' */
|
||||
return(get_match(unixname, p));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
|
||||
void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp, int len)
|
||||
{
|
||||
#if MAX_NAME_DOS_CACHE
|
||||
int k = -1;
|
||||
int besthit = -1;
|
||||
int maxhits = 0;
|
||||
DOSBUF *b;
|
||||
if (!vol->dosbuf) init_dosbuf(vol);
|
||||
b= (DOSBUF*)vol->dosbuf;
|
||||
uint8 wanted[14];
|
||||
uint8 rest[512];
|
||||
uint8 *slash;
|
||||
uint8 *parent_slash;
|
||||
DIR *d;
|
||||
|
||||
while (++k < MAX_NAME_DOS_CACHE) {
|
||||
int hits=vgl_name(b->cache[k], pp);
|
||||
if (hits < 0) {
|
||||
besthit=k;
|
||||
break;
|
||||
} else if (hits > maxhits) {
|
||||
besthit=k;
|
||||
maxhits =hits;
|
||||
}
|
||||
if (!vol || !unixname || !pp || !*pp || len <= 1) return;
|
||||
|
||||
slash=(uint8*)strchr((char*)pp, '/');
|
||||
memset(rest, 0, sizeof(rest));
|
||||
if (slash) {
|
||||
strmaxcpy(rest, slash, sizeof(rest)-1);
|
||||
*slash='\0';
|
||||
}
|
||||
if (maxhits > -1) {
|
||||
/* do not completely match */
|
||||
if (get_name(maxhits ? b->cache[besthit] : NULL,
|
||||
unixname, maxhits, pp)) {
|
||||
int k=MAX_NAME_DOS_CACHE-1;
|
||||
xfree(b->cache[k]);
|
||||
while (k--) {
|
||||
b->cache[k+1] = b->cache[k];
|
||||
|
||||
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;
|
||||
}
|
||||
b->cache[0] = NULL;
|
||||
new_str(b->cache[0], pp);
|
||||
}
|
||||
} else {
|
||||
strncpy(pp, b->cache[besthit], len-1);
|
||||
if (besthit > 2) {
|
||||
uint8 *sp=b->cache[besthit];
|
||||
while (besthit--) {
|
||||
b->cache[besthit+1] = b->cache[besthit];
|
||||
}
|
||||
b->cache[0] = sp;
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
#else
|
||||
get_match(unixname, pp-1);
|
||||
#endif
|
||||
|
||||
if (parent_slash) *parent_slash='/';
|
||||
if (slash) *slash='/';
|
||||
}
|
||||
|
||||
static inline int get_n_p(uint8 **p)
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "unxfile.h"
|
||||
#include "namspace.h"
|
||||
#include "nameos2.h"
|
||||
#include "namedos.h"
|
||||
|
||||
#if WITH_NAME_SPACE_CALLS
|
||||
|
||||
@@ -654,11 +655,13 @@ 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 +911,20 @@ 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));
|
||||
} else {
|
||||
return(sprintf(fname, "%ld.___", (long)e->nwpath.statb.st_ino));
|
||||
}
|
||||
char *parent_unix;
|
||||
int result;
|
||||
|
||||
if (!e || !fname || size_fname < 2) return(0);
|
||||
|
||||
parent_unix = alloc_nwpath2unix(&(e->nwpath), 1|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);
|
||||
xfree(parent_unix);
|
||||
return(result);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -1517,7 +1494,11 @@ 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 != '.') {
|
||||
build_dos_83_alias(vol_options, ds->unixname, name,
|
||||
dirbuff->d_ino, dname, size_dname);
|
||||
flag = fn_dos_match_old(dname, entry, vol_options);
|
||||
}
|
||||
} else if (namespace == NAME_OS2) {
|
||||
flag = (*name != '.' || (*(name+1) != '.' && *(name+1) != '\0' ))
|
||||
&& fn_os2_match(dname, entry, vol_options);
|
||||
|
||||
Reference in New Issue
Block a user