home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ixemul-45.0-src.tgz / tar.out / contrib / ixemul / library / convert_dir.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  6KB  |  206 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #define _KERNEL
  22. #include "ixemul.h"
  23. #include "kprintf.h"
  24. #include <string.h>
  25.  
  26. extern int __mread (), __mclose ();
  27.  
  28. #define BUFINCR    512
  29.  
  30. /* we're writing records that look like this to the `file' */
  31. struct file_dir {
  32.   long    fd_key;
  33.   long    fd_namelen;    /* padded to even size, thus perhaps zero padded */
  34.   char    fd_name[0];    /* fd_namelen bytes of filename */
  35. };
  36.  
  37. struct buffer {
  38.   u_char *buf, *bp, *bend;
  39.   int  buf_size;
  40. };
  41.  
  42. static int add_item(struct buffer *buf, long key, char *name)
  43. {
  44.   int len = strlen (name);
  45.   struct file_dir *fd;
  46.  
  47.   if ((buf->bp + (len + 2 + sizeof (struct file_dir))) >= buf->bend)
  48.     {
  49.       u_char *tmp;
  50.  
  51.       tmp = krealloc (buf->buf, buf->buf_size + BUFINCR);
  52.       if (!tmp)
  53.         {
  54.       ix_warning("ixemul.library: out of memory!");
  55.       kfree (buf->buf);
  56.       errno = ENOMEM;
  57.       return -1;
  58.     }
  59.  
  60.       buf->buf_size += BUFINCR;
  61.       buf->bp = tmp + (buf->bp - buf->buf);
  62.       buf->buf = tmp; 
  63.       buf->bend = tmp + buf->buf_size;
  64.     }
  65.  
  66.   fd = (struct file_dir *)buf->bp;
  67.   fd->fd_key = key;
  68.   fd->fd_namelen = len;
  69.   /* watch out for mc68000: don't let bp ever get odd ! */
  70.   if (fd->fd_namelen & 1) 
  71.     /* in that case zero pad the name */
  72.     fd->fd_name[fd->fd_namelen++] = 0;
  73.  
  74.   bcopy (name, fd->fd_name, len);
  75.   buf->bp += fd->fd_namelen + sizeof (struct file_dir);
  76.   return 0;
  77. }
  78.  
  79. /*
  80.  * Convert a directory into a DTYPE_MEM file.
  81.  *
  82.  * NOTE: function assumes:
  83.  *     o f is allocated and locked, it's packet is initialized
  84.  *       o name is an existing directory (S_IFDIR from a previous stat)
  85.  *     o signals are blocked (important! convert_dir() doesn't block them!)
  86.  */
  87.  
  88. char *convert_dir (struct file *f, char *name, int omask)
  89. {
  90.   BPTR lock;
  91.   struct buffer buf;
  92.   struct FileInfoBlock *fib;
  93.   int rc0;
  94.   char pathname[1024];
  95.  
  96.   fib = alloca (sizeof (*fib) + 2);
  97.   fib = LONG_ALIGN (fib);
  98.  
  99.   buf.buf = buf.bp = buf.bend = NULL;
  100.   buf.buf_size = 0;
  101.   lock = __lock (name, ACCESS_READ);
  102.   if (lock == 0 && IoErr() == 6262)  /* root directory */
  103.     {
  104.       struct DosList *dl;
  105.       int i = 3;
  106.  
  107.       /* put two dummy entries here.. some BSD code relies on the fact that
  108.        * it can safely skip the first two `.' and `..' entries ;-)) */
  109.       if (add_item(&buf, 1, "."))
  110.         goto do_return;
  111.       if (add_item(&buf, 2, ".."))
  112.         goto do_return;
  113.       
  114.       dl = LockDosList(LDF_VOLUMES | LDF_READ);
  115.       while ((dl = NextDosEntry(dl, LDF_VOLUMES)))
  116.         {
  117.           char name[256];
  118.           u_char *s = BTOCPTR(dl->dol_Name);
  119.  
  120.           memcpy(name, s + 1, *s);
  121.           name[*s] = 0;
  122.           if (add_item(&buf, i++, name))
  123.             break;
  124.         }
  125.       UnLockDosList(LDF_VOLUMES | LDF_READ);
  126.       if (dl)
  127.         goto do_return;
  128.       strcpy(pathname, "/");
  129.       goto read_directory;
  130.     }
  131.   else if (lock > 0)
  132.     {
  133.       rc0 = Examine (lock, fib);
  134.       NameFromLock(lock, pathname, sizeof(pathname));
  135.  
  136.       /* put two dummy entries here.. some BSD code relies on the fact that
  137.        * it can safely skip the first two `.' and `..' entries ;-)) */
  138.       if (add_item(&buf, 1, "."))
  139.         goto do_return;
  140.       if (add_item(&buf, 2, ".."))
  141.         goto do_return;
  142.       
  143.       /* don't include the dir-information into the file, *ix doesn't either. */
  144.       if (rc0 == -1)
  145.     for (;;)
  146.       {
  147.         /* allow for a clean abort out of a very long directory scan */
  148.         if (u.p_sig & ~omask)
  149.           {
  150.         /* if a signal is pending that was not blocked before entry to
  151.          * open(), break here and return with EINTR */
  152.         errno = EINTR;
  153.         kfree (buf.buf);
  154.         goto do_return;
  155.           }
  156.  
  157.         rc0 = ExNext (lock, fib);
  158.  
  159.             if (rc0 != -1)
  160.           break;
  161.  
  162.             if (add_item(&buf, (long)((struct FileLock *)(BTOCPTR(lock)))->fl_Key,
  163.                          fib->fib_FileName))
  164.               goto do_return;
  165.       }
  166.  
  167. read_directory:      
  168.       /* fine.. fill out the memory file object */
  169.       f->f_type        = DTYPE_MEM;
  170.       f->f_mf.mf_offset = 0;
  171.       f->f_mf.mf_buffer = buf.buf;
  172.       f->f_read        = __mread;
  173.       f->f_close    = __mclose;
  174.       f->f_ioctl    = 0;
  175.       f->f_select    = 0;
  176.       f->f_stb.st_size    = buf.bp - buf.buf;
  177.       /*
  178.        * have to use kmalloc() instead of malloc(), because this is no task-private
  179.        * data, it could (in the future) be shared by other tasks 
  180.        */
  181.       f->f_name = (void *)kmalloc(strlen(pathname) + 1);
  182.       if (f->f_name)
  183.         strcpy (f->f_name, pathname);
  184.  
  185.       /* NOTE: the rest of the stb should be ok from the previous stat() in
  186.        *       open() */
  187.       __unlock (lock);
  188.       return f->f_name;
  189.     }
  190.   else
  191.     {
  192.       errno = ENOENT;
  193.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  194.       return NULL;
  195.     }
  196.  
  197.   /* NOTE: granted, this is a bit spaghetti here.. the else above guarantees that
  198.            we won't unlock a lock we never got. So it's safe to unconditionally
  199.            unlock at the end. */
  200.  
  201. do_return:
  202.   __unlock (lock);
  203.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  204.   return NULL;
  205. }
  206.