0558 nwnss: import COMN Mac short name runtime

This commit is contained in:
ChatGPT
2026-06-15 17:19:20 +00:00
committed by Mario Fetka
parent c6e4c42593
commit 4f1a7e246b
5 changed files with 620 additions and 0 deletions

View File

@@ -30,6 +30,7 @@ add_library(nwnss SHARED
library/stdio/vprintf.c
library/stdio/vsprintf.c
library/stdlib/malloc.c
library/stdlib/strtol.c
library/stdlib/zalloc.c
library/stdlib/zrealloc.c
library/unicode/ByteToUnicode.c
@@ -96,7 +97,9 @@ add_library(nwnss SHARED
library/xString.c
nsslnxlib/nwlocale.c
comn/common/beastHash.c
comn/common/comnMacShortName.c
comn/common/comnVariableData.c
comn/common/zAPI.c
comn/namespace/dosNSWild.c
nss/cache/asyncio.c
nss/cache/bond.c

View File

@@ -0,0 +1,538 @@
/****************************************************************************
|
| (C) Copyright 2004 Novell, Inc.
| All Rights Reserved.
|
| This program is free software; you can redistribute it and/or
| modify it under the terms of version 2 of the GNU General Public
| License as published by the Free Software Foundation.
|
| 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, contact Novell, Inc.
|
| To contact Novell about this file by physical or electronic mail,
| you may find current contact information at www.novell.com
|
|***************************************************************************
|
| NetWare Advance File Services (PSS) module
|
|---------------------------------------------------------------------------
|
| $Author: vandana $
| $Modtime: $
|
| $Workfile: $
| $Revision: 1177 $
|
|---------------------------------------------------------------------------
| This module is used to:
| Provide compatibility with AFP 2.2 by providing a short (zid-mangled)
| file name for the AFP 3.1 255 unicode char file names
+-------------------------------------------------------------------------*/
#include <linux/module.h>
#include <stdio.h> // sprintf & COMN_RESOURCE
#include <ctype.h> // isxdigit
#include <string.h> // memcpy, strcpy, strlen, memset
#include <stdlib.h> // malloc/free
#include <xError.h> // error defines
#include "zParams.h" // zInfo at least
#include "nameSpace.h" // necessary for macNSpace.h
#include "macNSpace.h" // MACNS_LEGACY_NAME_LIMIT
/****************************************************************************
* Support routines to mangle 255 unicode char names to 31 byte-based
* names. This supports AFP 3.1 255 char names and provides back-wards
* compatibility for AFP 2.2 (31 char) names
*******************************************************************************/
/*************************************************************************
* Generate 31-char byte-based mangled name from 255 unicode name
**************************************************************************/
BOOL COMN_VerifyMangledMacName (unicode_t * mangledName, unicode_t * fileName)
{
static unicode_t testStr[] = L"???#";
unicode_t * baseEnd;
NINT baseLen;
baseEnd = unirchr (mangledName, '#');
if (!baseEnd) // no # in mangled name, return false
return FALSE;
baseLen = baseEnd - mangledName;
if (uninicmp (mangledName, fileName, baseLen ) == 0)
return TRUE;
// Check to see if first char is unmappable
if (uninicmp (mangledName, testStr, 4) == 0) // first char must be unmappable
{
if (!IS_UNICODE_MAPPABLE_TO_MAC_ASCII (*fileName)) // first char is unmappable
{
return TRUE;
}
}
// fileName does not match mangledName
return FALSE;
}
#define DOT_CHAR 0x002E
typedef struct parseInfo
{
BOOL mangleBase;
BOOL mangleExt;
BOOL dropExt;
unicode_t srcName[256];
unicode_t workingBase[32];
unicode_t workingExt [32];
unicode_t mangledName [32];
unicode_t mangleStr [32];
BYTE asciiName [32];
int baseLen;
int extLen;
} parseInfo;
void dropExt (struct parseInfo * info)
{
info->dropExt = TRUE;
info->mangleExt = FALSE;
info->workingExt[0] = 0;
info->extLen = 0;
}
// file name (base + extension) has more than 31 characters or
// must mangle (has unmappable chars)
unicode_t * generateMangledMacName (struct parseInfo * info, unicode_t * mangledName)
{
unicode_t dotChar[2];
dotChar[0] = 0x002E;
dotChar[1] = 0;
memset (mangledName, 0, sizeof (mangledName) );
memset (info->mangledName, 0, sizeof (info->mangledName) );
if (info->mangleBase && info->mangleExt)
{
info->workingExt[0] = 0;
info->mangleExt = FALSE;
info->dropExt = TRUE;
}
// is there room for the base name + mangled extension??
if ( (info->dropExt == FALSE) && (info->extLen != 0) )
{
{
if (info->mangleBase == FALSE)
{
if (unilen (info->workingBase) + unilen (info->mangleStr) + 1 <= 31)
info->mangleExt = TRUE;
}
}
}
// Does the base name need to be shortened?
if ( info->baseLen > (MACNS_LEGACY_NAME_LIMIT - (unilen (info->mangleStr) + 1) ) )
info->mangleBase = TRUE;
// Do we need to shorten the extension
if (info->extLen > (unilen (info->mangleStr) + 1) )
info->mangleExt = TRUE;
if (info->mangleBase && info->mangleExt)
{
dropExt (info);
}
if (info->mangleExt)
{
int minLen;
int additionalExtChars;
minLen = info->baseLen + unilen (info->mangleStr) + 1; // for the dot
additionalExtChars = MACNS_LEGACY_NAME_LIMIT - minLen;
if (additionalExtChars > info->extLen)
additionalExtChars = info->extLen;
// build ext from truncated ext + mangleString
LB_unicpy (mangledName, info->workingBase);
LB_unicat (mangledName, dotChar);
LB_unincat (mangledName, info->workingExt, additionalExtChars);
LB_unicat (mangledName, info->mangleStr);
LB_unicpy (info->mangledName, mangledName);
return (mangledName);
}
else // mangle base name, keep full extension if not dropping
{
int minLen;
int newBaseLen;
minLen = MACNS_LEGACY_NAME_LIMIT - (info->extLen + unilen (info->mangleStr));
if (minLen > LB_unilen (info->workingBase) )
newBaseLen = LB_unilen (info->workingBase);
else
newBaseLen = minLen;
mangledName[0] = 0;
LB_unincat (mangledName, info->workingBase, newBaseLen);
LB_unicat (mangledName, info->mangleStr);
if (info->dropExt == FALSE)
{
LB_unicat (mangledName, dotChar);
LB_unicat (mangledName, info->workingExt);
}
LB_unicpy (info->mangledName, mangledName);
return (mangledName);
}
}
// generate MangleString from zid
unicode_t * getMangleString (unicode_t * mangleStr, LONG zID)
{
char buffer[256];
unicode_t * uPtr = mangleStr;
char * chPtr;
memset (buffer, 0, 256);
buffer[0] = '#';
sprintf (&buffer[1], "%x", zID);
uPtr = mangleStr;
*uPtr = 0;
chPtr = &buffer[0];
/* convert ASCII hex digit string to unicode */
while (*chPtr)
*uPtr++ = *chPtr++;
*uPtr = 0;
if (*mangleStr != 0)
return (mangleStr);
else
return (NULL);
}
static STATUS parseFileName (parseInfo * info, unicode_t * srcFileName)
{
unicode_t * lastDotPtr, *srcPtr;
char byteFileName [zMAX_COMPONENT_NAME];
// STATUS err;
memset (info, 0, sizeof (*info));
memset (byteFileName, 0, sizeof (byteFileName) );
LB_unicpy (info->srcName, srcFileName);
// find base & extension
// extension - look at first dot from end of file name
lastDotPtr = LB_unirchr (srcFileName, DOT_CHAR /* period or dot */);
if (lastDotPtr)
info->extLen = LB_unilen (lastDotPtr);
if (lastDotPtr == NULL) // no extension
info->dropExt = TRUE;
else
*lastDotPtr = 0; // terminate base file name for now
// find base file name
// copy base to workingBaseName (first 31 chars only)
memset (info->workingBase, 0, sizeof (info->workingBase) );
// zero out, because unincpy does not always null terminate
// src is > 31 chars, no null terminator is added to string
LB_unincpy (info->workingBase, srcFileName, MACNS_LEGACY_NAME_LIMIT);
info->baseLen = LB_unilen (srcFileName);
if (lastDotPtr) // restore dot to filename, overwrite null terminator we added
*lastDotPtr = DOT_CHAR;
// if (base len > 31)
// set mangleBase = true
if (info->baseLen > MACNS_LEGACY_NAME_LIMIT)
info->mangleBase = TRUE;
if (info->extLen > MACNS_LEGACY_NAME_LIMIT)
info->mangleExt = TRUE;
if (info->mangleBase && info->mangleExt)
{
dropExt (info);
}
if (info->dropExt == FALSE) // there is an extension
{
// if (extLen > 31)
// copy first 31 chars to newExt
// set mangleExt = true
// else
// copy extension to workingExt
// unincpy does not always null terminate dest string
memset (info->workingExt, 0, sizeof (info->workingExt) );
LB_unincpy (info->workingExt, lastDotPtr + 1, MACNS_LEGACY_NAME_LIMIT);
// if there is an unmappable char in extension
// truncate workingExtension at unmappable char
// set mangleExt = true
srcPtr = info->workingExt;
// terminate at first unmappable char position
while (*srcPtr != 0)
{
if (!IS_UNICODE_MAPPABLE_TO_MAC_ASCII(*srcPtr))
{
*srcPtr = 0;
info->mangleExt = TRUE;
}
else
{
srcPtr++;
}
}
}
// base - check base for unmappable
// if (firstChar is unmappable)
// substitute ??? for file name in workingBaseName
// set mangleBase to true
// else
// tuncate at first unmappable in workingBaseName
// set mangleBase to true
if (info->baseLen > 0) // filename doesn't start with dot
{
int len = 0;
srcPtr = info->workingBase;
// terminate at first unmappable char position
while (*srcPtr != 0)
{
if (!IS_UNICODE_MAPPABLE_TO_MAC_ASCII(*srcPtr))
{
*srcPtr = 0;
info->mangleBase = TRUE;
}
else
{
srcPtr++;
}
}
len = LB_unilen (info->workingBase);
if (len == 0) // first char is unmappable
{
info->workingBase[0] = '?';
info->workingBase[1] = '?';
info->workingBase[2] = '?';
info->workingBase[3] = 0;
}
}
return (0);
}
STATUS COMN_MakeShortMacFileName (zInfo_s * zSrcInfo, unicode_t * uniFileName, BYTE * macByteName)
{
unicode_t * mangleStr = NULL;
unicode_t * uPtr;
parseInfo * info = NULL;
unicode_t * mangledName = NULL;
STATUS rc = 0;
if (uniFileName)
*uniFileName = 0;
if (macByteName)
*macByteName = 0;
mangleStr = malloc(256);
if (mangleStr == NULL)
{
// printf ("Unable to allocate Mangle String buffer\r\n");
rc = zERR_NO_MEMORY;
goto Cleanup;
}
mangledName = malloc (256);
if (mangledName == NULL)
{
// printf ("Unable to allocate mangledName buffer\r\n");
rc = zERR_NO_MEMORY;
goto Cleanup;
}
info = malloc (sizeof (*info) );
if (info == NULL)
{
// printf ("Unable to allocate parse info structure\r\n");
rc = zERR_NO_MEMORY;
goto Cleanup;
}
uPtr = zInfoGetFileName(zSrcInfo, zNSPACE_MAC);
if (uPtr == NULL)
{
rc = zERR_NO_NAMES_IN_PATH;
goto Cleanup;
}
rc = parseFileName (info, uPtr);
if (rc != zOK)
goto Cleanup;
uPtr = getMangleString (mangleStr, zSrcInfo->std.zid);
if (uPtr == NULL)
{
rc = zERR_AFP_MAKE_STRING_FROM_ZID_FAILED;
goto Cleanup;
}
LB_unicpy (info->mangleStr, mangleStr);
if (!info->mangleBase && !info->mangleExt &&
(info->baseLen + info->extLen + 1 <= MACNS_LEGACY_NAME_LIMIT) )
{
LB_unicpy (uniFileName, info->srcName);
goto Cleanup;
}
generateMangledMacName (info, mangledName);
if (uniFileName)
LB_unicpy (uniFileName, info->mangledName);
if (macByteName)
{
NINT retLen;
rc = LB_UnicodeToMacByte(NSS_UNI_CONVERSION_RAW,
(char *)&(info->asciiName),
sizeof (info->asciiName), mangledName, &retLen);
if (rc != zOK)
{
strcpy (info->asciiName, "??");
}
else
strcpy (macByteName, info->asciiName);
}
Cleanup:
if (mangleStr)
free(mangleStr);
if (mangledName)
free (mangledName);
if (info)
free (info);
return rc;
}
/****************************************************************************
* Determine if file name matches the #zid mangled format
* Mangled format is 31 chars or less with embedded zid like
* #zid.ext or name.ext#zid or name#zid
****************************************************************************/
LONG COMN_GetZidFromMangledName (unicode_t * fileName)
{
// make sure file name is <= 31 chars (unmappable char may generate < 31 chars)
// algorithm - check for first # from end
// check for dot in file name and replace it with a NULL terminator
// move ptr up one.
// check if all characters are valid hex numbers
// convert uni to ascii
// convert ascii hex to LONG
// If no valid zid format in name, return 0, else return zid
unicode_t * uPtr;
utf8_t * utf8Ptr;
BYTE * bPtr, *endPtr;
LONG id;
BYTE buf [80];
BYTE idStr [32]; // buffer for #nnn string, 10 bytes should be enough #nnn + null terminator
// if (getMacNameLimit() > MACNS_LEGACY_NAME_LIMIT)
// return 0; // extended Mac namespace is not enabled
if (unilen (fileName) > MACNS_LEGACY_NAME_LIMIT) // unmappable chars in file name can be < 31
return 0; // can't be a generated mangled ID
uPtr = unirchr (fileName, '#');
if (uPtr == NULL)
return 0; // no # in file name, therefore, no ID in name
utf8Ptr = &idStr[0];
uni2utf (uPtr, utf8Ptr, unilen (uPtr) + 1 );
buf[0] = 0x2E; // DOT_CHAR
bPtr = strchr ((char *) utf8Ptr, '.');
if (bPtr) // if we found a dot
*bPtr = 0x0; // null terminate at dot
bPtr = idStr + 1; // set ptr to start of string
if ( strlen (bPtr) > 8 ) // value will be more than a LONG
return 0;
bPtr = idStr + 1;
while (*bPtr)
{
if ( isxdigit (*bPtr) )
bPtr++;
else
return 0; // not hex string digit, not an ID
}
// if we get this far, we have something that starts with a # sign
// and contains only hex digits
bPtr = idStr + 1; // position past # sign and convert hex string
id = LB_strtol( bPtr, (char **)&endPtr, 16 ); // convert hex string to LONG
return id;
}

View File

@@ -0,0 +1,33 @@
/****************************************************************************
|
| (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc.
| All Rights Reserved.
|
| Source(s): public_core/comn/common/zAPI.c
|
| Minimal userspace import of the zInfo name accessor needed by the COMN
| namespace/name helper path. The function body is kept equivalent to the
| NSS source and does not perform disk or VFS IO.
+-------------------------------------------------------------------------*/
#include <stddef.h>
#include <zPublics.h>
unicode_t *zInfoGetFileName(zInfo_s *info, NINT nameSpace)
{
LONG *fileNames;
if (info->infoVersion > zINFO_VERSION_D) {
return NULL;
}
if (nameSpace >= info->names.numEntries) {
return NULL;
}
if (info->names.fileNameArray == 0) {
return NULL;
}
fileNames = (LONG *)&((BYTE *)info)[info->names.fileNameArray];
if (fileNames[nameSpace] == 0) {
return NULL;
}
return (unicode_t *)&(((BYTE *)info)[fileNames[nameSpace]]);
}

View File

@@ -0,0 +1,17 @@
/****************************************************************************
|
| (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc.
| All Rights Reserved.
|
| Source(s): NSS libNSS stdlib export ABI, shared/sdk/library/xStdlib.h
|
| This userspace port preserves the NSS LB_strtol symbol and delegates the
| libc-near conversion to the host C library.
+-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <library/xStdlib.h>
long int LB_strtol(const char *nptr, char **endptr, int base)
{
return strtol(nptr, endptr, base);
}

View File

@@ -45,6 +45,7 @@
#include <nCache.h>
#include <volume.h>
#include "dosNSpace.h"
#include <library/xStdlib.h>
#define CHECK(expr) do { \
if (!(expr)) { \
@@ -84,6 +85,7 @@ int main(void)
CHECK(LB_isxdigit('A'));
CHECK(sizeof(FullDirectoryInfo_s) >= sizeof(unicode_t));
CHECK(COMN_MakeShortMacFileName == COMN_MakeShortMacFileName);
CHECK(LB_strtol("1f", NULL, 16) == 31);
CHECK(sizeof(ObjectIDCacheCtrl_s) >= sizeof(DQhead_t));
CHECK(CACHE_Startup == CACHE_Startup);
CHECK(BEASTHASH_Remove == BEASTHASH_Remove);
@@ -117,5 +119,32 @@ int main(void)
CHECK(DOSNS_wildReplace(NULL, src_pattern, src_name, NULL, answer) == zOK);
CHECK(unicode_equals_ascii(answer, "FOO.TXT"));
{
struct {
zInfo_s info;
LONG names[2];
unicode_t mac_name[8];
} sample;
unicode_t out_name[64];
BYTE out_mac[64];
memset(&sample, 0, sizeof(sample));
sample.info.infoVersion = zINFO_VERSION_D;
sample.info.names.numEntries = 2;
sample.info.names.fileNameArray = (LONG)((BYTE *)sample.names - (BYTE *)&sample.info);
sample.names[zNSPACE_MAC] = (LONG)((BYTE *)sample.mac_name - (BYTE *)&sample.info);
sample.mac_name[0] = 'R';
sample.mac_name[1] = 'E';
sample.mac_name[2] = 'A';
sample.mac_name[3] = 'D';
sample.mac_name[4] = 'M';
sample.mac_name[5] = 'E';
sample.mac_name[6] = 0;
CHECK(zInfoGetFileName(&sample.info, zNSPACE_MAC) == sample.mac_name);
CHECK(COMN_MakeShortMacFileName(&sample.info, out_name, out_mac) == zOK);
CHECK(unicode_equals_ascii(out_name, "README"));
}
return 0;
}