mirror of
https://frontier.innolan.net/github/amiga-ixemul.git
synced 2026-09-12 13:22:45 +00:00
564 lines
10 KiB
C
564 lines
10 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.
|
|
*/
|
|
|
|
#define _KERNEL
|
|
#include <string.h>
|
|
#include "ixemul.h"
|
|
#include "kprintf.h"
|
|
|
|
#include <utility/tagitem.h>
|
|
#include <dos/dostags.h>
|
|
|
|
#if 0
|
|
|
|
struct open_vec {
|
|
int action;
|
|
struct FileHandle *fh;
|
|
};
|
|
|
|
static int
|
|
__open_func (struct lockinfo *info, struct open_vec *ov, int *error)
|
|
{
|
|
struct StandardPacket *sp = &info->sp;
|
|
|
|
sp->sp_Pkt.dp_Type = ov->action;
|
|
sp->sp_Pkt.dp_Arg1 = CTOBPTR (ov->fh);
|
|
sp->sp_Pkt.dp_Arg2 = info->parent_lock;
|
|
sp->sp_Pkt.dp_Arg3 = info->bstr;
|
|
|
|
PutPacket (info->handler, sp);
|
|
__wait_sync_packet (sp);
|
|
|
|
info->result = sp->sp_Pkt.dp_Res1;
|
|
*error = info->result != -1;
|
|
|
|
/* handler is supposed to supply this, but if it didn't... */
|
|
if (!*error && !ov->fh->fh_Type) ov->fh->fh_Type = info->handler;
|
|
|
|
/* continue if we failed because of symlink - reference */
|
|
return 1;
|
|
}
|
|
|
|
BPTR
|
|
__open (char *name, int action)
|
|
{
|
|
unsigned long *fh;
|
|
struct open_vec ov;
|
|
BPTR res;
|
|
struct Process *this_proc = NULL;
|
|
APTR oldwin = NULL;
|
|
char buf[32], *s, *p = buf;
|
|
|
|
if ((name[0] == '/' && strncmp(name, "/dev/", 5)) ||
|
|
index(name, ':'))
|
|
{
|
|
s = (name[0] == '/') ? name + 1 : name;
|
|
while (*s && *s != '/' && *s != ':')
|
|
*p++ = *s++;
|
|
*p++ = ':';
|
|
*p = '\0';
|
|
if (ix.ix_flags & ix_no_insert_disk_requester)
|
|
{
|
|
this_proc = (struct Process *)SysBase->ThisTask;
|
|
oldwin = this_proc->pr_WindowPtr;
|
|
this_proc->pr_WindowPtr = (APTR)-1;
|
|
}
|
|
if (!IsFileSystem(buf)) /* if NAME is not a file system but */
|
|
/* something like a pipe or console, then */
|
|
/* do NOT use __plock() but call Open directly */
|
|
{
|
|
if (!*s)
|
|
res = Open(buf, action);
|
|
else if (*s == '/')
|
|
{
|
|
*s = ':';
|
|
res = Open(name + 1, action);
|
|
*s = '/';
|
|
}
|
|
else
|
|
res = Open(name, action);
|
|
if (ix.ix_flags & ix_no_insert_disk_requester)
|
|
this_proc->pr_WindowPtr = oldwin;
|
|
return res;
|
|
}
|
|
if (ix.ix_flags & ix_no_insert_disk_requester)
|
|
this_proc->pr_WindowPtr = oldwin;
|
|
}
|
|
|
|
/* needed to get berserk ReadArgs() to behave sane, GRRR */
|
|
fh = AllocDosObjectTags (DOS_FILEHANDLE, ADO_FH_Mode, action, TAG_DONE);
|
|
if (! fh)
|
|
return 0;
|
|
ov.fh = (struct FileHandle *) fh;
|
|
ov.action = action;
|
|
|
|
res = __plock (name, __open_func, &ov);
|
|
|
|
/* check for opening of NIL:, in which case we just return
|
|
a filehandle with a zero handle field */
|
|
if (!res && IoErr() == 4242)
|
|
{
|
|
res = -1;
|
|
}
|
|
|
|
if (!res)
|
|
FreeDosObject (DOS_FILEHANDLE, fh);
|
|
|
|
return res ? CTOBPTR(ov.fh) : 0;
|
|
}
|
|
#else
|
|
|
|
#if 1
|
|
|
|
/*
|
|
* ix_to_ados © 2005 Harry Sintonen <sintonen@iki.fi>
|
|
*/
|
|
|
|
char *
|
|
ix_to_ados(char *buf, const char *name)
|
|
{
|
|
usetup;
|
|
if (u.u_parent_userdata)u_ptr=u.u_parent_userdata;
|
|
if (u.u_use_amiga_paths){
|
|
strcpy (buf,name);
|
|
return buf;
|
|
}
|
|
char *p;
|
|
const char *q = name;
|
|
int allowdot = 1;
|
|
int dotcnt = 0;
|
|
int root = 0;
|
|
int absados = 0;
|
|
|
|
KPRINTF(("name \"%s\"\n", name));
|
|
|
|
if (u.u_is_root)
|
|
{
|
|
root = 1;
|
|
}
|
|
else if (*q == '/')
|
|
{
|
|
root = 1;
|
|
q++;
|
|
}
|
|
|
|
#if 1
|
|
/* allow amigados paths concatenated to nix ones */
|
|
p = strrchr(q, ':');
|
|
if (p)
|
|
{
|
|
dotcnt = -1;
|
|
q = p + 1;
|
|
while ((p + dotcnt >= name) && p[dotcnt] != ':' && p[dotcnt] != '/')
|
|
dotcnt--;
|
|
memcpy(buf, p + dotcnt + 1, -dotcnt);
|
|
p = buf - dotcnt;
|
|
|
|
root = 0;
|
|
dotcnt = 0;
|
|
absados = 1;
|
|
}
|
|
else
|
|
#endif
|
|
p = buf;
|
|
|
|
for (;;)
|
|
{
|
|
char c = *q++;
|
|
|
|
switch (c)
|
|
{
|
|
case '.':
|
|
if (allowdot)
|
|
dotcnt++;
|
|
else
|
|
*p++ = '.';
|
|
break;
|
|
|
|
case '/':
|
|
case '\0':
|
|
if (dotcnt > 2)
|
|
{
|
|
int cnt = dotcnt;
|
|
while (cnt--)
|
|
*p++ = '.';
|
|
if (root == 1)
|
|
root++;
|
|
}
|
|
if (root == 2 || (root == 1 && c == '\0'))
|
|
{
|
|
*p++ = ':';
|
|
root = 0;
|
|
}
|
|
else if ((root == 0 && absados == 0) &&
|
|
(dotcnt == 2 || /* "/../" */
|
|
((dotcnt == 0 || dotcnt > 2) && c != '\0'))) /* normal "/" */
|
|
{
|
|
*p++ = '/';
|
|
}
|
|
|
|
if (c == '\0')
|
|
goto out;
|
|
|
|
while (*q == '/')
|
|
q++;
|
|
|
|
allowdot = 1;
|
|
dotcnt = 0;
|
|
break;
|
|
|
|
#if 0
|
|
case ':':
|
|
dotcnt = -2;
|
|
while (*q == ':')
|
|
{
|
|
q++; dotcnt--;
|
|
}
|
|
|
|
while ((q + dotcnt >= name) && q[dotcnt] != ':' && q[dotcnt] != '/')
|
|
dotcnt--;
|
|
dotcnt++;
|
|
memcpy(buf, q + dotcnt, -dotcnt);
|
|
p = buf - dotcnt;
|
|
|
|
root = 0;
|
|
allowdot = 1; /* allow foo:../ */
|
|
dotcnt = 0;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
if (root == 1)
|
|
root++;
|
|
while (dotcnt--)
|
|
*p++ = '.';
|
|
*p++ = c;
|
|
allowdot = 0;
|
|
dotcnt = 0;
|
|
absados = 0;
|
|
break;
|
|
}
|
|
}
|
|
out:
|
|
|
|
/* remove lonely '/' from the end */
|
|
if (p > buf + 2 && p[-1] == '/' && p[-2] != '/' && p[-2] != ':')
|
|
p--;
|
|
|
|
*p = '\0';
|
|
|
|
KPRINTF(("result \"%s\"\n", buf));
|
|
|
|
if (!strcasecmp(buf, "console:"))
|
|
{
|
|
buf[0] = '*';
|
|
buf[1] = '\0';
|
|
}
|
|
else if (!strncmp(buf, "dev:", 4))
|
|
{
|
|
if (!strcmp(buf + 4, "tty"))
|
|
{
|
|
buf[0] = '*';
|
|
buf[1] = '\0';
|
|
}
|
|
else if (!strcmp(buf + 4, "null"))
|
|
{
|
|
strcpy(buf, "NIL:");
|
|
}
|
|
else if (!strcmp(buf + 4, "random") || !strcmp(buf + 4, "urandom") || !strcmp(buf + 4, "srandom") || !strcmp(buf + 4, "prandom"))
|
|
{
|
|
strcpy(buf, "RANDOM:");
|
|
}
|
|
else if (!strcmp(buf + 4, "zero"))
|
|
{
|
|
strcpy(buf, "ZERO:");
|
|
}
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
#else
|
|
|
|
char *
|
|
ix_to_ados(char *buf, const char *name)
|
|
{
|
|
usetup;
|
|
char *p = buf;
|
|
const char *q = name;
|
|
int parent_count = 0;
|
|
|
|
KPRINTF(("name \"%s\"\n", name));
|
|
|
|
if (u.u_is_root)
|
|
{
|
|
*p++ = '/';
|
|
}
|
|
|
|
while (*q)
|
|
{
|
|
if (*q == '/')
|
|
{
|
|
if (p > buf && p[-1] == '/')
|
|
{
|
|
--p;
|
|
}
|
|
else
|
|
{
|
|
p = buf;
|
|
parent_count = 0;
|
|
}
|
|
}
|
|
else if (*q == '.' && (q[1] == '/' || q[1] == '\0'))
|
|
{
|
|
++q;
|
|
if (*q)
|
|
++q;
|
|
continue;
|
|
}
|
|
else if (*q == '.' && q[1] == '.' && (q[2] == '/' || q[2] == '\0'))
|
|
{
|
|
q += 2;
|
|
|
|
if (p == buf)
|
|
{
|
|
++parent_count;
|
|
if (*q)
|
|
++q;
|
|
continue;
|
|
}
|
|
else if (p == buf + 1 && *buf == '/')
|
|
{
|
|
p = buf;
|
|
parent_count = 0;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
--p;
|
|
}
|
|
while (p > buf && p[-1] != '/');
|
|
if (p > buf + 1)
|
|
--p;
|
|
else
|
|
{
|
|
while (*q == '/')
|
|
{
|
|
++q;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const char *start = q;
|
|
|
|
do
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
while (*q && *q != '/' && *q != ':');
|
|
|
|
if (*q == ':')
|
|
{
|
|
p = buf;
|
|
*p++ = '/';
|
|
while (start != q)
|
|
*p++ = *start++;
|
|
}
|
|
}
|
|
|
|
if (*q == '/' || *q == ':')
|
|
{
|
|
*p++ = '/';
|
|
++q;
|
|
}
|
|
}
|
|
|
|
if (p == buf + 1 && buf[0] == '/')
|
|
{
|
|
buf[0] = ':';
|
|
*p = '\0';
|
|
}
|
|
else
|
|
{
|
|
if (p > buf && p[-1] == '/')
|
|
--p;
|
|
|
|
*p++ = '\0';
|
|
|
|
if (parent_count)
|
|
{
|
|
while (p != buf)
|
|
{
|
|
--p;
|
|
p[parent_count] = *p;
|
|
}
|
|
do
|
|
{
|
|
*p++ = '/';
|
|
}
|
|
while (--parent_count);
|
|
}
|
|
else if (*buf == '/')
|
|
{
|
|
++buf;
|
|
p = buf;
|
|
while (*p != '/' && *p)
|
|
++p;
|
|
if (!*p)
|
|
p[1] = '\0';
|
|
*p = ':';
|
|
}
|
|
}
|
|
|
|
KPRINTF(("result \"%s\"\n", buf));
|
|
|
|
if (!strcasecmp(buf, "console:"))
|
|
{
|
|
buf[0] = '*';
|
|
buf[1] = '\0';
|
|
}
|
|
else if (!strncmp(buf, "dev:", 4))
|
|
{
|
|
if (!strcmp(buf + 4, "tty"))
|
|
{
|
|
buf[0] = '*';
|
|
buf[1] = '\0';
|
|
}
|
|
else if (!strcmp(buf + 4, "null"))
|
|
{
|
|
strcpy(buf, "NIL:");
|
|
}
|
|
else if (!strcmp(buf + 4, "random") || !strcmp(buf + 4, "urandom") || !strcmp(buf + 4, "srandom") || !strcmp(buf + 4, "prandom"))
|
|
{
|
|
strcpy(buf, "RANDOM:");
|
|
}
|
|
else if (!strcmp(buf + 4, "zero"))
|
|
{
|
|
strcpy(buf, "ZERO:");
|
|
}
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
#endif
|
|
|
|
char *check_root(char *name)
|
|
{
|
|
//char buf[256];
|
|
//dprintf("check_root(%s)\n", name);
|
|
if (*name == '/')
|
|
{
|
|
BPTR olddir = CurrentDir(0);
|
|
BPTR dir = DupLock(olddir);
|
|
int root = 0;
|
|
//NameFromLock(olddir, buf, sizeof(buf));
|
|
//dprintf("curdir <%s>\n", buf);
|
|
|
|
CurrentDir(olddir);
|
|
|
|
do
|
|
{
|
|
BPTR parent = ParentDir(dir);
|
|
|
|
++name;
|
|
//dprintf("dir %p parent %p name <%s>\n", dir, parent, name);
|
|
if (parent == 0)
|
|
{
|
|
root = 1;
|
|
break;
|
|
}
|
|
|
|
UnLock(dir);
|
|
dir = parent;
|
|
}
|
|
while (*name == '/');
|
|
|
|
UnLock(dir);
|
|
|
|
while (*name == '/')
|
|
++name;
|
|
|
|
if (!root)
|
|
{
|
|
name = NULL;
|
|
}
|
|
else if (*name)
|
|
{
|
|
char *p = name;
|
|
do
|
|
{
|
|
++p;
|
|
}
|
|
while (*p && *p != '/');
|
|
|
|
if (*p)
|
|
{
|
|
*p = ':';
|
|
}
|
|
else
|
|
{
|
|
p[0] = ':';
|
|
p[1] = '\0';
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
name = NULL;
|
|
}
|
|
//dprintf("return(%s)\n",name ?name: "NULL");
|
|
return name;
|
|
}
|
|
|
|
BPTR
|
|
__open (char *name, int action)
|
|
{
|
|
BPTR file;
|
|
APTR win;
|
|
struct Process *me = (APTR) SysBase->ThisTask;
|
|
char *buf = alloca(strlen(name) + 4);
|
|
buf = ix_to_ados(buf, name);
|
|
win = me->pr_WindowPtr;
|
|
me->pr_WindowPtr = (APTR)-1;
|
|
file = Open(buf, action);
|
|
if (!file)
|
|
{
|
|
LONG err = IoErr();
|
|
if (err == ERROR_OBJECT_NOT_FOUND)
|
|
{
|
|
buf = check_root(buf);
|
|
if (buf && *buf)
|
|
{
|
|
file = Open(buf, action);
|
|
if (file)
|
|
err = 0;
|
|
}
|
|
SetIoErr(err);
|
|
}
|
|
}
|
|
me->pr_WindowPtr = win;
|
|
return file;
|
|
}
|
|
|
|
#endif
|