mirror of
https://github.com/adtools/clib2.git
synced 2025-12-08 14:59:05 +00:00
- Replaced ISO Latin 1 code #160 with a plain blank space (ASCII code #32) where necessary git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@15305 87f5fb63-7c3d-0410-a384-fd976d0f7a62
282 lines
6.8 KiB
C
282 lines
6.8 KiB
C
/*
|
|
* $Id: unistd_translatea2u.c,v 1.7 2006-01-08 12:04:27 obarthel Exp $
|
|
*
|
|
* :ts=4
|
|
*
|
|
* Portable ISO 'C' (1994) runtime library for the Amiga computer
|
|
* Copyright (c) 2002-2015 by Olaf Barthel <obarthel (at) gmx.net>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* - Neither the name of Olaf Barthel nor the names of contributors
|
|
* may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef _UNISTD_HEADERS_H
|
|
#include "unistd_headers.h"
|
|
#endif /* _UNISTD_HEADERS_H */
|
|
|
|
/****************************************************************************/
|
|
|
|
int
|
|
__translate_amiga_to_unix_path_name(char const ** name_ptr,struct name_translation_info * nti)
|
|
{
|
|
const int max_unix_len = sizeof(nti->substitute)-1;
|
|
char local_replacement[sizeof(nti->substitute)];
|
|
BOOL have_double_slash;
|
|
int len,replace_len;
|
|
int result = ERROR;
|
|
int i;
|
|
char * replace;
|
|
char * name;
|
|
|
|
assert( name_ptr != NULL && (*name_ptr) != NULL && nti != NULL );
|
|
|
|
replace = nti->substitute;
|
|
|
|
name = (char *)(*name_ptr);
|
|
|
|
/* Check if the name would become too long to handle. */
|
|
len = strlen(name);
|
|
if(len >= (int)sizeof(nti->substitute))
|
|
{
|
|
D(("path name '%s' is too long (%ld characters total; maximum is %ld)!",name,len,sizeof(nti->substitute)-1));
|
|
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
/* Reduce any '//' embedded in the name if possible. */
|
|
have_double_slash = FALSE;
|
|
|
|
for(i = 0 ; i < len-1 ; i++)
|
|
{
|
|
if(name[i] == '/' && name[i+1] == '/')
|
|
{
|
|
have_double_slash = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(have_double_slash)
|
|
{
|
|
/* We will need to make a copy of the name. Make sure that it fits. */
|
|
if(len > max_unix_len)
|
|
{
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
strcpy(local_replacement,name);
|
|
name = local_replacement;
|
|
|
|
len = __strip_double_slash(name,len);
|
|
}
|
|
|
|
/* The empty string corresponds to the current
|
|
* directory, which is the ".".
|
|
*/
|
|
if(len == 0)
|
|
{
|
|
strcpy(replace,".");
|
|
}
|
|
else
|
|
{
|
|
char * volume_name;
|
|
int volume_name_len;
|
|
|
|
/* Figure out if the path includes a volume, device or assignment name.
|
|
If so, strip it from the path, to be translated and added later. */
|
|
volume_name = NULL;
|
|
volume_name_len = 0;
|
|
|
|
for(i = 0 ; i < len ; i++)
|
|
{
|
|
if(name[i] == ':')
|
|
{
|
|
volume_name = name;
|
|
volume_name_len = i;
|
|
|
|
name += volume_name_len+1;
|
|
len -= volume_name_len+1;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Replace all "/" characters in the name which don't just act as
|
|
* separators with "..". Otherwise, copy the name string to the
|
|
* replacement buffer.
|
|
*/
|
|
replace_len = 0;
|
|
|
|
while(name[0] == '/')
|
|
{
|
|
if(replace_len + 3 > max_unix_len)
|
|
{
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
memmove(&replace[replace_len],"../",3);
|
|
replace_len += 3;
|
|
|
|
name++;
|
|
len--;
|
|
|
|
if(len == 0)
|
|
{
|
|
/* Strip the trailing '/'. */
|
|
replace[--replace_len] = '\0';
|
|
}
|
|
}
|
|
|
|
for(i = 0 ; i < len ; i++)
|
|
{
|
|
if(name[i] == '/' && (name[i+1] == '/' || name[i+1] == '\0'))
|
|
{
|
|
if(replace_len + 3 > max_unix_len)
|
|
{
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
memmove(&replace[replace_len],"/..",3);
|
|
replace_len += 3;
|
|
}
|
|
else
|
|
{
|
|
if(replace_len + 1 > max_unix_len)
|
|
{
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
replace[replace_len++] = name[i];
|
|
}
|
|
}
|
|
|
|
assert( replace_len <= max_unix_len );
|
|
|
|
replace[replace_len] = '\0';
|
|
|
|
/* If necessary, add and translate the volume name found above. */
|
|
if(volume_name != NULL)
|
|
{
|
|
/* Check if the complete path will fit. This assumes the worst
|
|
case scenario. */
|
|
if(1 + volume_name_len + 1 + replace_len > max_unix_len)
|
|
{
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
if(volume_name_len > 0)
|
|
{
|
|
if(replace_len > 0)
|
|
{
|
|
/* Add the volume name in front of the path. */
|
|
memmove(&replace[1 + volume_name_len + 1],replace,(size_t)(replace_len+1));
|
|
replace[0] = replace[1 + volume_name_len] = '/';
|
|
memmove(&replace[1],volume_name,(size_t)volume_name_len);
|
|
}
|
|
else
|
|
{
|
|
/* There is only the volume name. */
|
|
replace[0] = '/';
|
|
memmove(&replace[1],volume_name,(size_t)volume_name_len);
|
|
replace[volume_name_len + 1] = '\0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int path_prefix_len = 0;
|
|
|
|
/* We need to expand ':'. If the current directory name is
|
|
known and refers to an absolute path, we borrow the
|
|
absolute path name component. */
|
|
if(__current_path_name[0] != '\0')
|
|
{
|
|
int path_name_len;
|
|
|
|
path_name_len = strlen(__current_path_name);
|
|
|
|
/* Figure out where the absolute path name portion ends. */
|
|
for(i = 1 ; i <= path_name_len ; i++)
|
|
{
|
|
if(__current_path_name[i] == '/' ||
|
|
__current_path_name[i] == '\0')
|
|
{
|
|
path_prefix_len = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If we found the absolute path name portion, use it. */
|
|
if(path_prefix_len > 0)
|
|
{
|
|
if(path_prefix_len + 1 + replace_len > max_unix_len)
|
|
{
|
|
__set_errno(ENAMETOOLONG);
|
|
goto out;
|
|
}
|
|
|
|
if(replace_len > 0)
|
|
{
|
|
memmove(&replace[path_prefix_len + 1],replace,(size_t)(replace_len+1));
|
|
memmove(replace,__current_path_name,(size_t)path_prefix_len);
|
|
replace[path_prefix_len] = '/';
|
|
}
|
|
else
|
|
{
|
|
memmove(replace,__current_path_name,(size_t)path_prefix_len);
|
|
replace[path_prefix_len] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if(path_prefix_len == 0)
|
|
{
|
|
/* The ':foo' path gets translated into '/foo'. */
|
|
memmove(&replace[1],replace,(size_t)(replace_len+1));
|
|
replace[0] = '/';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
name = replace;
|
|
|
|
assert( strlen(name) < (size_t)max_unix_len );
|
|
|
|
nti->original_name = (char *)(*name_ptr);
|
|
(*name_ptr) = name;
|
|
|
|
D(("translated '%s' to '%s'",nti->original_name,name));
|
|
|
|
result = OK;
|
|
|
|
out:
|
|
|
|
return(result);
|
|
}
|