home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / library / rcs / convert_dir.c,v < prev    next >
Encoding:
Text File  |  1992-07-28  |  7.2 KB  |  304 lines

  1. head    1.2;
  2. access;
  3. symbols
  4.     version39-41:1.1;
  5. locks;
  6. comment    @ *  @;
  7.  
  8.  
  9. 1.2
  10. date    92.07.28.00.42.36;    author mwild;    state Exp;
  11. branches;
  12. next    1.1;
  13.  
  14. 1.1
  15. date    92.05.14.19.55.40;    author mwild;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @convert an AmigaDOS directory into a pseudo directory file
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @fix signals, fix memory leak, fix possible never unlocked lock
  28. @
  29. text
  30. @/*
  31.  *  This file is part of ixemul.library for the Amiga.
  32.  *  Copyright (C) 1991, 1992  Markus M. Wild
  33.  *
  34.  *  This library is free software; you can redistribute it and/or
  35.  *  modify it under the terms of the GNU Library General Public
  36.  *  License as published by the Free Software Foundation; either
  37.  *  version 2 of the License, or (at your option) any later version.
  38.  *
  39.  *  This library is distributed in the hope that it will be useful,
  40.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  41.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  42.  *  Library General Public License for more details.
  43.  *
  44.  *  You should have received a copy of the GNU Library General Public
  45.  *  License along with this library; if not, write to the Free
  46.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  47.  *
  48.  *  $Id: convert_dir.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
  49.  *
  50.  *  $Log: convert_dir.c,v $
  51.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  52.  *  Initial revision
  53.  *
  54.  */
  55.  
  56. #define KERNEL
  57. #include "ixemul.h"
  58.  
  59. #undef DEBUG
  60.  
  61. #ifdef DEBUG
  62. #define DP(a) kprintf a
  63. #else
  64. #define DP(a)
  65. #endif
  66.  
  67. /* don't need to use the async port, no more than 1 task will be in here
  68.  * at a time and use our packet */
  69. #define __srwport (u.u_sync_mp)
  70.  
  71. extern int __mread (), __mclose ();
  72.  
  73. extern void *kmalloc (size_t), *krealloc (void *, size_t);
  74.  
  75. #if __GNUC__ != 2
  76. #define alloca __builtin_alloca
  77. #endif
  78.  
  79. #define BUFINCR    512
  80.  
  81. /* we're writing records that look like this to the `file' */
  82. struct file_dir {
  83.   long    fd_key;
  84.   long    fd_namelen;    /* padded to even size, thus perhaps zero padded */
  85.   char    fd_name[0];    /* fd_namelen bytes of filename */
  86. };
  87.  
  88. /*
  89.  * Convert a directory into a DTYPE_MEM file.
  90.  *
  91.  * NOTE: function assumes:
  92.  *     o f is allocated and locked, it's packet is initialized
  93.  *       o name is an existing directory (S_IFDIR from a previous stat)
  94.  *     o signals are blocked (important! convert_dir() doesn't block them!)
  95.  */
  96.  
  97. int
  98. convert_dir (struct file *f, char *name, int omask)
  99. {
  100.   BPTR lock;
  101.   u_char *buf, *bp, *bend;
  102.   int  buf_size;
  103.   struct FileInfoBlock *fib;
  104.   struct StandardPacket *sp;
  105.   struct MsgPort *handler;
  106.   struct file_dir *fd;
  107.   int len, res, err;
  108.  
  109.   fib = alloca (sizeof (*fib) + 2);
  110.   fib = LONG_ALIGN (fib);
  111.   
  112.   res = 0;
  113.   if ((lock = __lock (name, ACCESS_READ)) > 0)
  114.     {
  115.       buf = kmalloc (BUFINCR);
  116.       buf_size = BUFINCR;
  117.       bp = buf;
  118.       bend = buf + buf_size;
  119.       sp = &f->f_sp;
  120.       handler = ((struct FileLock *)(BTOCPTR (lock))) -> fl_Task;
  121.  
  122.       /* make sure we got that memory */
  123.       if (! buf)
  124.         {
  125.           err = ENOMEM;
  126.           res = -1;
  127.           goto do_return;
  128.         }
  129.       
  130.       sp->sp_Pkt.dp_Port = __srwport;
  131.       sp->sp_Pkt.dp_Type = ACTION_EXAMINE_OBJECT;
  132.       sp->sp_Pkt.dp_Arg1 = lock;
  133.       sp->sp_Pkt.dp_Arg2 = CTOBPTR (fib);
  134.       PutPacket (handler, sp);
  135.       __wait_sync_packet (sp);
  136.  
  137.       /* put two dummy entries here.. some BSD code relies on the fact that
  138.        * it can safely skip the first two `.' and `..' entries ;-)) */
  139.       fd = (struct file_dir *) bp;
  140.       fd->fd_key = 1;
  141.       fd->fd_namelen = 2;
  142.       fd->fd_name[0] = '.'; fd->fd_name[1] = 0;
  143.       bp += fd->fd_namelen + sizeof (struct file_dir);
  144.       fd = (struct file_dir *) bp;
  145.       fd->fd_key = 2;
  146.       fd->fd_namelen = 2;
  147.       fd->fd_name[0] = '.'; fd->fd_name[1] = '.';
  148.       bp += fd->fd_namelen + sizeof (struct file_dir);
  149.       
  150.       /* don't include the dir-information into the file, *ix doesn't either. */
  151.       if (sp->sp_Pkt.dp_Res1 == -1)
  152.     for (;;)
  153.       {
  154.         /* allow for a clean abort out of a very long directory scan */
  155.         if (u.p_sig & ~omask)
  156.           {
  157.         /* if a signal is pending that was not blocked before entry to
  158.          * open(), break here and return with EINTR */
  159.         res = -1;
  160.         err = EINTR;
  161.         kfree (buf);
  162.         goto do_return;
  163.           }
  164.  
  165.         sp->sp_Pkt.dp_Port = __srwport;
  166.         sp->sp_Pkt.dp_Type = ACTION_EXAMINE_NEXT;
  167.         sp->sp_Pkt.dp_Arg1 = lock;
  168.         sp->sp_Pkt.dp_Arg2 = CTOBPTR (fib);
  169.         PutPacket (handler, sp);
  170.         __wait_sync_packet (sp);
  171.         
  172.             if (sp->sp_Pkt.dp_Res1 != -1) break;
  173.  
  174.         /* tricky tricky... if working with packets, names are BSTRs... */
  175.             len = fib->fib_FileName[0];
  176.  
  177. #if 0
  178. /* this was just a debugging aid */
  179.         if ((unsigned)len > 30)
  180.           ix_panic ("ixemul.library: too long name (> 30 characters)!");
  181. #endif
  182.  
  183.             if ((bp + (len + 2 + sizeof (struct file_dir))) >= bend)
  184.           {
  185.             u_char *tmp;
  186.  
  187. DP(("cd: buf = $%lx, bp = $%lx, bend = $%lx, new = $%lx.\n", buf, bp, bend, len + 1 + sizeof (fd)));
  188.  
  189.             tmp = krealloc (buf, buf_size + BUFINCR);
  190.             if (! tmp)
  191.           {
  192.             ix_panic ("ixemul.library: out of memory!");
  193.             res = -1;
  194.             kfree (buf);
  195.             err = ENOMEM;
  196.             goto do_return;
  197.           }
  198.  
  199.             buf_size += BUFINCR;
  200.             bp = tmp + (bp-buf);
  201.             buf = tmp; 
  202.         bend = tmp + buf_size;
  203. DP(("cd2: buf = $%lx, bp = $%lx, bend = $%lx, new = $%lx.\n", buf, bp, bend, len + 1 + sizeof (fd)));
  204.           }
  205.  
  206.         fd = (struct file_dir *) bp;
  207.             fd->fd_key = fib->fib_DiskKey;
  208.             fd->fd_namelen = len;
  209.             /* watch out for mc68000: don't let bp ever get odd ! */
  210.             if (fd->fd_namelen & 1) 
  211.           /* in that case zero pad the name */
  212.           fd->fd_name[fd->fd_namelen++] = 0;
  213.  
  214.         bcopy (fib->fib_FileName + 1, fd->fd_name, len);
  215.         bp += fd->fd_namelen + sizeof (struct file_dir);
  216. #ifdef DEBUG
  217.         if (bp >= bend || & fd->fd_name[len] >= bend)
  218.           {
  219.               DP(("cd: OVERFLOW! bp = $%lx, bend = $%lx, len = $%lx, &fd->fd_name[len] = $%lx\n",
  220.             bp, bend, len, & fd->fd_name[len]));
  221.           }
  222. #endif
  223.       }
  224.       
  225.       /* fine.. fill out the memory file object */
  226.       f->f_type        = DTYPE_MEM;
  227.       f->f_mf.mf_offset = 0;
  228.       f->f_mf.mf_buffer = buf;
  229.       f->f_read        = __mread;
  230.       f->f_close    = __mclose;
  231.       f->f_ioctl    = 0;
  232.       f->f_select    = 0;
  233.       f->f_stb.st_size    = bp-buf;
  234.       /* NOTE: the rest of the stb should be ok from the previous stat() in
  235.        *       open() */
  236.     }
  237.   else
  238.     {
  239.       errno = ENOENT;
  240.       return -1;
  241.     }
  242.  
  243.   /* NOTE: granted, this is a bit spaghetti here.. the else above guarantees that
  244.            we won't unlock a lock we never got. So it's safe to unconditionally
  245.            unlock at the end. */
  246.  
  247. do_return:
  248.   __unlock (lock);
  249.   errno = err;
  250.   return res;
  251. }
  252. @
  253.  
  254.  
  255. 1.1
  256. log
  257. @Initial revision
  258. @
  259. text
  260. @d19 1
  261. a19 1
  262.  *  $Id$
  263. d21 4
  264. a24 1
  265.  *  $Log$
  266. d65 1
  267. a65 1
  268.  *     o signals are blocked
  269. d69 1
  270. a69 1
  271. convert_dir (struct file *f, char *name)
  272. d78 1
  273. a78 1
  274.   int len, res, omask, err;
  275. a83 1
  276.   omask = syscall (SYS_sigsetmask, ~0);
  277. d92 8
  278. d128 2
  279. a129 2
  280.         /* if a signal is pending that is otherwise not blocked,
  281.          * break here, and return with EINTR */
  282. d133 1
  283. a133 2
  284.         bp = buf = 0;
  285.         break;
  286. a164 1
  287.             /* this way we get a zero length directory */
  288. a165 1
  289.             bp = buf = 0;
  290. d167 1
  291. a167 1
  292.             break;
  293. a206 2
  294.  
  295.       __unlock (lock);
  296. d209 8
  297. a216 1
  298.     res = -1;
  299. d218 2
  300. a219 2
  301.   syscall (SYS_sigsetmask, omask);
  302.   
  303. @
  304.