mirror of
https://github.com/adtools/clib2.git
synced 2026-05-02 10:16:27 +00:00
The readlink() function now uses DOS packet I/O instead of trusting Lock() to do the right thing
This commit is contained in:
@@ -58,9 +58,19 @@ readlink(const char * path_name, char * buffer, int buffer_size)
|
||||
struct name_translation_info path_name_nti;
|
||||
struct name_translation_info buffer_nti;
|
||||
#endif /* UNIX_PATH_SEMANTICS */
|
||||
|
||||
D_S(struct bcpl_name, bname);
|
||||
const size_t name_size = sizeof(bname->name);
|
||||
|
||||
BPTR lock = ZERO;
|
||||
int result = ERROR;
|
||||
int target_length = -1;
|
||||
struct DevProc *dvp = NULL;
|
||||
char * new_name = NULL;
|
||||
char * path_part;
|
||||
size_t name_len;
|
||||
size_t new_name_size;
|
||||
LONG readlink_result;
|
||||
LONG error;
|
||||
|
||||
ENTER();
|
||||
|
||||
@@ -70,12 +80,12 @@ readlink(const char * path_name, char * buffer, int buffer_size)
|
||||
|
||||
assert( path_name != NULL && buffer != NULL );
|
||||
|
||||
if(__check_abort_enabled)
|
||||
if (__check_abort_enabled)
|
||||
__check_abort();
|
||||
|
||||
#if defined(CHECK_FOR_NULL_POINTERS)
|
||||
{
|
||||
if(path_name == NULL || buffer == NULL)
|
||||
if (path_name == NULL || buffer == NULL)
|
||||
{
|
||||
SHOWSTRING("invalid parameters");
|
||||
|
||||
@@ -87,9 +97,9 @@ readlink(const char * path_name, char * buffer, int buffer_size)
|
||||
|
||||
#if defined(UNIX_PATH_SEMANTICS)
|
||||
{
|
||||
if(__unix_path_semantics)
|
||||
if (__unix_path_semantics)
|
||||
{
|
||||
if(path_name[0] == '\0')
|
||||
if (path_name[0] == '\0')
|
||||
{
|
||||
SHOWMSG("no name given");
|
||||
|
||||
@@ -97,53 +107,144 @@ readlink(const char * path_name, char * buffer, int buffer_size)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(__translate_unix_to_amiga_path_name(&path_name,&path_name_nti) != 0)
|
||||
if (__translate_unix_to_amiga_path_name(&path_name, &path_name_nti) != 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif /* UNIX_PATH_SEMANTICS */
|
||||
|
||||
D(("trying to get a lock on '%s'",path_name));
|
||||
name_len = strlen(path_name);
|
||||
if (name_len >= name_size)
|
||||
{
|
||||
SHOWMSG("name too long");
|
||||
|
||||
SetIoErr(ERROR_LINE_TOO_LONG);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Convert the name into a BCPL string. */
|
||||
bname->name[0] = name_len;
|
||||
memcpy(&bname->name[1], path_name, name_len);
|
||||
|
||||
/* Get a handle on the device, volume or assignment name in the path. */
|
||||
dvp = GetDeviceProc((STRPTR)path_name, dvp);
|
||||
if (dvp == NULL)
|
||||
{
|
||||
SHOWMSG("dvp == NULL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Try to obtain a lock on the object. It should be a link and not
|
||||
* a file or directory.
|
||||
*/
|
||||
lock = DoPkt(dvp->dvp_Port, ACTION_LOCATE_OBJECT, dvp->dvp_Lock, MKBADDR(bname), SHARED_LOCK, 0, 0);
|
||||
if (lock != ZERO)
|
||||
{
|
||||
SHOWMSG("lock != ZERO");
|
||||
|
||||
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = IoErr();
|
||||
|
||||
if (error != ERROR_IS_SOFT_LINK)
|
||||
{
|
||||
SHOWMSG("not a soft link");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We only need the leading path name. */
|
||||
name_len = ((BYTE *)PathPart(path_name)) - (BYTE *)path_name;
|
||||
|
||||
path_part = malloc(name_len+1);
|
||||
if (path_part == NULL)
|
||||
{
|
||||
SHOWMSG("path_part too long");
|
||||
|
||||
SetIoErr(ERROR_NO_FREE_STORE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(path_part, path_name, name_len);
|
||||
path_part[name_len] = '\0';
|
||||
|
||||
PROFILE_OFF();
|
||||
lock = __lock((STRPTR)path_name,SHARED_LOCK,&target_length,buffer,(size_t)buffer_size);
|
||||
lock = Lock((STRPTR)path_part, SHARED_LOCK);
|
||||
PROFILE_ON();
|
||||
|
||||
if(lock != ZERO)
|
||||
new_name_size = name_size+1;
|
||||
|
||||
/* Provide as much buffer space as possible. */
|
||||
if (buffer_size > 0 && (size_t)buffer_size > new_name_size)
|
||||
new_name_size = buffer_size;
|
||||
|
||||
/* For soft link resolution we need a temporary buffer to
|
||||
let the file system store the resolved path name in. */
|
||||
new_name = malloc(new_name_size);
|
||||
if (new_name == NULL)
|
||||
{
|
||||
__set_errno(EINVAL);
|
||||
goto out;
|
||||
}
|
||||
else if (target_length <= 0) /* No a soft-link. */
|
||||
{
|
||||
__set_errno(__translate_io_error_to_errno(IoErr()));
|
||||
SHOWMSG("new_name too long");
|
||||
|
||||
SetIoErr(ERROR_NO_FREE_STORE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(UNIX_PATH_SEMANTICS)
|
||||
/* Now ask the file system to resolve the entire path. */
|
||||
readlink_result = ReadLink(dvp->dvp_Port, lock, (STRPTR)FilePart(path_name), (STRPTR)new_name, (LONG)new_name_size);
|
||||
if (readlink_result < 0)
|
||||
{
|
||||
if(__unix_path_semantics)
|
||||
SHOWMSG("ReadLink");
|
||||
|
||||
/* This will return either -1 (resolution error) or -2
|
||||
(buffer too small). We regard both as trouble. */
|
||||
SetIoErr(ERROR_INVALID_COMPONENT_NAME);
|
||||
goto out;
|
||||
}
|
||||
|
||||
assert( result > 0 );
|
||||
|
||||
/* If the caller supplied a buffer, copy as much of the name
|
||||
as possible into it. */
|
||||
if (buffer != NULL && buffer_size > 0)
|
||||
{
|
||||
strlcpy(buffer, new_name, buffer_size);
|
||||
|
||||
#if defined(UNIX_PATH_SEMANTICS)
|
||||
{
|
||||
if(__translate_amiga_to_unix_path_name((char const **)&buffer,&buffer_nti) != 0)
|
||||
goto out;
|
||||
if (__unix_path_semantics)
|
||||
{
|
||||
if (__translate_amiga_to_unix_path_name((char const **)&buffer, &buffer_nti) != 0)
|
||||
goto out;
|
||||
|
||||
__restore_path_name((char const **)&buffer,&buffer_nti);
|
||||
__restore_path_name((char const **)&buffer,&buffer_nti);
|
||||
|
||||
strcpy(buffer,buffer_nti.substitute);
|
||||
strcpy(buffer, buffer_nti.substitute);
|
||||
}
|
||||
}
|
||||
#endif /* UNIX_PATH_SEMANTICS */
|
||||
|
||||
result = strlen(buffer);
|
||||
|
||||
SHOWSTRING(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
#endif /* UNIX_PATH_SEMANTICS */
|
||||
|
||||
result = strlen(buffer);
|
||||
|
||||
SHOWSTRING(buffer);
|
||||
|
||||
out:
|
||||
|
||||
PROFILE_OFF();
|
||||
|
||||
if (dvp != NULL)
|
||||
FreeDeviceProc(dvp);
|
||||
|
||||
UnLock(lock);
|
||||
|
||||
PROFILE_ON();
|
||||
|
||||
RETURN(result);
|
||||
return(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user