mirror of
https://frontier.innolan.net/github/amiga-ixemul.git
synced 2026-09-12 20:03:58 +00:00
240 lines
4.9 KiB
C
240 lines
4.9 KiB
C
/*
|
|
* This file is part of ixemul.library for the Amiga.
|
|
* Copyright (C) 1991, 1992 Markus M. Wild
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* $Id: readlink.c,v 1.1.1.1 2005/03/15 15:57:09 laire Exp $
|
|
*/
|
|
|
|
#define _KERNEL
|
|
#include "ixemul.h"
|
|
#include "kprintf.h"
|
|
|
|
#include <string.h>
|
|
|
|
#ifndef ERROR_IS_SOFT_LINK
|
|
#define ERROR_IS_SOFT_LINK 233
|
|
#endif
|
|
|
|
#ifndef ACTION_READ_LINK
|
|
#define ACTION_READ_LINK 1024
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
struct readlink_vec {
|
|
char *buf;
|
|
int bufsize;
|
|
};
|
|
|
|
static int
|
|
__readlink_func (struct lockinfo *info, struct readlink_vec *rv, int *error)
|
|
{
|
|
struct StandardPacket *sp = &info->sp;
|
|
|
|
/* this baby uses CSTRings, absolutely unique... */
|
|
sp->sp_Pkt.dp_Type = ACTION_READ_LINK;
|
|
sp->sp_Pkt.dp_Arg1 = info->parent_lock;
|
|
sp->sp_Pkt.dp_Arg2 = (long)info->str + 1;
|
|
sp->sp_Pkt.dp_Arg3 = (long)rv->buf;
|
|
sp->sp_Pkt.dp_Arg4 = rv->bufsize;
|
|
|
|
PutPacket (info->handler, sp);
|
|
__wait_sync_packet (sp);
|
|
|
|
info->result = sp->sp_Pkt.dp_Res1;
|
|
|
|
*error = info->result <= 0;
|
|
|
|
/* this *can't* be a symlink... */
|
|
return 0;
|
|
}
|
|
|
|
int readlink(const char *path, char *buf, int bufsiz)
|
|
{
|
|
struct readlink_vec rv;
|
|
struct stat stb;
|
|
int rc;
|
|
usetup;
|
|
|
|
/* readlink is buggy in the current fs release (37.26 here), in that
|
|
it reports OBJECT_NOT_FOUND if a file is present but not a
|
|
symbolic link */
|
|
if (syscall(SYS_lstat, path, &stb) == 0)
|
|
{
|
|
if (S_ISLNK (stb.st_mode))
|
|
{
|
|
rv.buf = alloca(bufsiz);
|
|
rv.bufsize = bufsiz;
|
|
|
|
rc = __plock ((char *)path, __readlink_func, &rv);
|
|
if (rc <= 0)
|
|
{
|
|
errno = __ioerr_to_errno (IoErr ());
|
|
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
|
|
}
|
|
else
|
|
{
|
|
int len = a2u(NULL, rv.buf);
|
|
char *p = alloca(len);
|
|
|
|
a2u(p, rv.buf);
|
|
if (p[0] == '.' && p[1] == '/') /* skip ./ */
|
|
{
|
|
p += 2;
|
|
len -= 2;
|
|
}
|
|
rc = (len - 1 < bufsiz ? len - 1 : bufsiz);
|
|
memcpy(buf, p, rc);
|
|
if (rc < bufsiz)
|
|
buf[rc] = '\0';
|
|
}
|
|
return rc > 0 ? rc : -1;
|
|
}
|
|
else
|
|
{
|
|
errno = EINVAL;
|
|
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
|
|
}
|
|
}
|
|
/* errno should be set already by lstat() */
|
|
return -1;
|
|
}
|
|
|
|
#else
|
|
|
|
char *ix_to_ados(char *, const char *);
|
|
|
|
int readlink(const char *path, char *buf, int bufsiz)
|
|
{
|
|
struct stat stb;
|
|
int rc = 0;
|
|
int omask;
|
|
usetup;
|
|
|
|
/* readlink is buggy in the current fs release (37.26 here), in that
|
|
it reports OBJECT_NOT_FOUND if a file is present but not a
|
|
symbolic link */
|
|
if (syscall(SYS_lstat, path, &stb) == 0)
|
|
{
|
|
if (S_ISLNK (stb.st_mode))
|
|
{
|
|
char *apath = alloca(strlen(path) + 3);
|
|
char *dest = alloca(bufsiz);
|
|
struct DevProc *dvp;
|
|
|
|
apath = ix_to_ados(apath, path);
|
|
|
|
omask = syscall(SYS_sigsetmask, ~0);
|
|
|
|
dvp = GetDeviceProc(apath, NULL);
|
|
if (dvp)
|
|
{
|
|
rc = ReadLink(dvp->dvp_Port, dvp->dvp_Lock, apath, dest, bufsiz);
|
|
FreeDeviceProc(dvp);
|
|
}
|
|
|
|
syscall(SYS_sigsetmask, omask);
|
|
|
|
if (rc == 0)
|
|
{
|
|
errno = __ioerr_to_errno (IoErr ());
|
|
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
|
|
}
|
|
else
|
|
{
|
|
int len = a2u(NULL, dest);
|
|
char *p = alloca(len);
|
|
|
|
a2u(p, dest);
|
|
if (p[0] == '.' && p[1] == '/') /* skip ./ */
|
|
{
|
|
p += 2;
|
|
len -= 2;
|
|
}
|
|
rc = (len - 1 < bufsiz ? len - 1 : bufsiz);
|
|
memcpy(buf, p, rc);
|
|
if (rc < bufsiz)
|
|
buf[rc] = '\0';
|
|
}
|
|
return rc > 0 ? rc : -1;
|
|
}
|
|
else
|
|
{
|
|
errno = EINVAL;
|
|
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
|
|
}
|
|
}
|
|
/* errno should be set already by lstat() */
|
|
return -1;
|
|
}
|
|
|
|
#endif
|
|
|
|
int a2u(char *buf, char *src)
|
|
{
|
|
int len = 0;
|
|
|
|
if (index(src, ':'))
|
|
{
|
|
if (buf)
|
|
buf[len] = '/';
|
|
len++;
|
|
while (*src != ':')
|
|
{
|
|
if (buf)
|
|
buf[len] = *src;
|
|
len++;
|
|
src++;
|
|
}
|
|
src++;
|
|
}
|
|
else
|
|
{
|
|
if (buf)
|
|
buf[len] = '.';
|
|
len++;
|
|
}
|
|
while (*src)
|
|
{
|
|
if (*src == '/')
|
|
{
|
|
if (buf)
|
|
strcpy(buf + len, "/..");
|
|
len += 3;
|
|
src++;
|
|
}
|
|
else
|
|
{
|
|
if (buf)
|
|
buf[len] = '/';
|
|
len++;
|
|
while (*src && *src != '/')
|
|
{
|
|
if (buf)
|
|
buf[len] = *src;
|
|
src++;
|
|
len++;
|
|
}
|
|
if (*src)
|
|
src++;
|
|
}
|
|
}
|
|
if (buf)
|
|
buf[len] = '\0';
|
|
return len + 1;
|
|
}
|