home *** CD-ROM | disk | FTP | other *** search
- head 1.2;
- access;
- symbols
- version39-41:1.1;
- locks;
- comment @ * @;
-
-
- 1.2
- date 92.07.28.00.42.36; author mwild; state Exp;
- branches;
- next 1.1;
-
- 1.1
- date 92.05.14.19.55.40; author mwild; state Exp;
- branches;
- next ;
-
-
- desc
- @convert an AmigaDOS directory into a pseudo directory file
- @
-
-
- 1.2
- log
- @fix signals, fix memory leak, fix possible never unlocked lock
- @
- text
- @/*
- * 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: convert_dir.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
- *
- * $Log: convert_dir.c,v $
- * Revision 1.1 1992/05/14 19:55:40 mwild
- * Initial revision
- *
- */
-
- #define KERNEL
- #include "ixemul.h"
-
- #undef DEBUG
-
- #ifdef DEBUG
- #define DP(a) kprintf a
- #else
- #define DP(a)
- #endif
-
- /* don't need to use the async port, no more than 1 task will be in here
- * at a time and use our packet */
- #define __srwport (u.u_sync_mp)
-
- extern int __mread (), __mclose ();
-
- extern void *kmalloc (size_t), *krealloc (void *, size_t);
-
- #if __GNUC__ != 2
- #define alloca __builtin_alloca
- #endif
-
- #define BUFINCR 512
-
- /* we're writing records that look like this to the `file' */
- struct file_dir {
- long fd_key;
- long fd_namelen; /* padded to even size, thus perhaps zero padded */
- char fd_name[0]; /* fd_namelen bytes of filename */
- };
-
- /*
- * Convert a directory into a DTYPE_MEM file.
- *
- * NOTE: function assumes:
- * o f is allocated and locked, it's packet is initialized
- * o name is an existing directory (S_IFDIR from a previous stat)
- * o signals are blocked (important! convert_dir() doesn't block them!)
- */
-
- int
- convert_dir (struct file *f, char *name, int omask)
- {
- BPTR lock;
- u_char *buf, *bp, *bend;
- int buf_size;
- struct FileInfoBlock *fib;
- struct StandardPacket *sp;
- struct MsgPort *handler;
- struct file_dir *fd;
- int len, res, err;
-
- fib = alloca (sizeof (*fib) + 2);
- fib = LONG_ALIGN (fib);
-
- res = 0;
- if ((lock = __lock (name, ACCESS_READ)) > 0)
- {
- buf = kmalloc (BUFINCR);
- buf_size = BUFINCR;
- bp = buf;
- bend = buf + buf_size;
- sp = &f->f_sp;
- handler = ((struct FileLock *)(BTOCPTR (lock))) -> fl_Task;
-
- /* make sure we got that memory */
- if (! buf)
- {
- err = ENOMEM;
- res = -1;
- goto do_return;
- }
-
- sp->sp_Pkt.dp_Port = __srwport;
- sp->sp_Pkt.dp_Type = ACTION_EXAMINE_OBJECT;
- sp->sp_Pkt.dp_Arg1 = lock;
- sp->sp_Pkt.dp_Arg2 = CTOBPTR (fib);
- PutPacket (handler, sp);
- __wait_sync_packet (sp);
-
- /* put two dummy entries here.. some BSD code relies on the fact that
- * it can safely skip the first two `.' and `..' entries ;-)) */
- fd = (struct file_dir *) bp;
- fd->fd_key = 1;
- fd->fd_namelen = 2;
- fd->fd_name[0] = '.'; fd->fd_name[1] = 0;
- bp += fd->fd_namelen + sizeof (struct file_dir);
- fd = (struct file_dir *) bp;
- fd->fd_key = 2;
- fd->fd_namelen = 2;
- fd->fd_name[0] = '.'; fd->fd_name[1] = '.';
- bp += fd->fd_namelen + sizeof (struct file_dir);
-
- /* don't include the dir-information into the file, *ix doesn't either. */
- if (sp->sp_Pkt.dp_Res1 == -1)
- for (;;)
- {
- /* allow for a clean abort out of a very long directory scan */
- if (u.p_sig & ~omask)
- {
- /* if a signal is pending that was not blocked before entry to
- * open(), break here and return with EINTR */
- res = -1;
- err = EINTR;
- kfree (buf);
- goto do_return;
- }
-
- sp->sp_Pkt.dp_Port = __srwport;
- sp->sp_Pkt.dp_Type = ACTION_EXAMINE_NEXT;
- sp->sp_Pkt.dp_Arg1 = lock;
- sp->sp_Pkt.dp_Arg2 = CTOBPTR (fib);
- PutPacket (handler, sp);
- __wait_sync_packet (sp);
-
- if (sp->sp_Pkt.dp_Res1 != -1) break;
-
- /* tricky tricky... if working with packets, names are BSTRs... */
- len = fib->fib_FileName[0];
-
- #if 0
- /* this was just a debugging aid */
- if ((unsigned)len > 30)
- ix_panic ("ixemul.library: too long name (> 30 characters)!");
- #endif
-
- if ((bp + (len + 2 + sizeof (struct file_dir))) >= bend)
- {
- u_char *tmp;
-
- DP(("cd: buf = $%lx, bp = $%lx, bend = $%lx, new = $%lx.\n", buf, bp, bend, len + 1 + sizeof (fd)));
-
- tmp = krealloc (buf, buf_size + BUFINCR);
- if (! tmp)
- {
- ix_panic ("ixemul.library: out of memory!");
- res = -1;
- kfree (buf);
- err = ENOMEM;
- goto do_return;
- }
-
- buf_size += BUFINCR;
- bp = tmp + (bp-buf);
- buf = tmp;
- bend = tmp + buf_size;
- DP(("cd2: buf = $%lx, bp = $%lx, bend = $%lx, new = $%lx.\n", buf, bp, bend, len + 1 + sizeof (fd)));
- }
-
- fd = (struct file_dir *) bp;
- fd->fd_key = fib->fib_DiskKey;
- fd->fd_namelen = len;
- /* watch out for mc68000: don't let bp ever get odd ! */
- if (fd->fd_namelen & 1)
- /* in that case zero pad the name */
- fd->fd_name[fd->fd_namelen++] = 0;
-
- bcopy (fib->fib_FileName + 1, fd->fd_name, len);
- bp += fd->fd_namelen + sizeof (struct file_dir);
- #ifdef DEBUG
- if (bp >= bend || & fd->fd_name[len] >= bend)
- {
- DP(("cd: OVERFLOW! bp = $%lx, bend = $%lx, len = $%lx, &fd->fd_name[len] = $%lx\n",
- bp, bend, len, & fd->fd_name[len]));
- }
- #endif
- }
-
- /* fine.. fill out the memory file object */
- f->f_type = DTYPE_MEM;
- f->f_mf.mf_offset = 0;
- f->f_mf.mf_buffer = buf;
- f->f_read = __mread;
- f->f_close = __mclose;
- f->f_ioctl = 0;
- f->f_select = 0;
- f->f_stb.st_size = bp-buf;
- /* NOTE: the rest of the stb should be ok from the previous stat() in
- * open() */
- }
- else
- {
- errno = ENOENT;
- return -1;
- }
-
- /* NOTE: granted, this is a bit spaghetti here.. the else above guarantees that
- we won't unlock a lock we never got. So it's safe to unconditionally
- unlock at the end. */
-
- do_return:
- __unlock (lock);
- errno = err;
- return res;
- }
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d19 1
- a19 1
- * $Id$
- d21 4
- a24 1
- * $Log$
- d65 1
- a65 1
- * o signals are blocked
- d69 1
- a69 1
- convert_dir (struct file *f, char *name)
- d78 1
- a78 1
- int len, res, omask, err;
- a83 1
- omask = syscall (SYS_sigsetmask, ~0);
- d92 8
- d128 2
- a129 2
- /* if a signal is pending that is otherwise not blocked,
- * break here, and return with EINTR */
- d133 1
- a133 2
- bp = buf = 0;
- break;
- a164 1
- /* this way we get a zero length directory */
- a165 1
- bp = buf = 0;
- d167 1
- a167 1
- break;
- a206 2
-
- __unlock (lock);
- d209 8
- a216 1
- res = -1;
- d218 2
- a219 2
- syscall (SYS_sigsetmask, omask);
-
- @
-