1
0
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:
Olaf Barthel
2025-07-14 13:33:02 +02:00
parent d9b2c0f38f
commit 9f1a9ae92e

View File

@@ -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;
}