home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / library / readlink.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  4KB  |  182 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  readlink.c,v 1.1.1.1 1994/04/04 04:30:31 amiga Exp
  20.  *
  21.  *  readlink.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:31  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1992/05/18  12:22:32  mwild
  26.  *  set errno, and only send READLINK packet if the file really is a symlink
  27.  *
  28.  * Revision 1.1  1992/05/14  19:55:40  mwild
  29.  * Initial revision
  30.  *
  31.  */
  32.  
  33. #define _KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36.  
  37. #include <string.h>
  38.  
  39. #ifndef ERROR_IS_SOFT_LINK
  40. #define ERROR_IS_SOFT_LINK  233
  41. #endif
  42.  
  43. #ifndef ACTION_READ_LINK
  44. #define ACTION_READ_LINK 1024
  45. #endif
  46.  
  47. struct readlink_vec {
  48.   char *buf;
  49.   int bufsize;
  50. };
  51.  
  52. static int a2u(char *buf, char *src);
  53.  
  54. static int
  55. __readlink_func (struct StandardPacket *sp, struct MsgPort *handler,
  56.                  BPTR parent_lock,
  57.              BSTR name,
  58.              struct readlink_vec *rv, int *no_error)
  59. {
  60.   /* this baby uses CSTRings, absolutely unique... */
  61.   unsigned char *np = BTOCPTR (name);
  62.   np[*np + 1] = 0; np++;
  63.  
  64.   sp->sp_Pkt.dp_Type = ACTION_READ_LINK;
  65.   sp->sp_Pkt.dp_Arg1 = parent_lock;
  66.   sp->sp_Pkt.dp_Arg2 = (long) np;
  67.   sp->sp_Pkt.dp_Arg3 = (long) rv->buf;
  68.   sp->sp_Pkt.dp_Arg4 = rv->bufsize;
  69.  
  70.   PutPacket (handler, sp);
  71.   __wait_sync_packet (sp);
  72.  
  73.   *no_error = sp->sp_Pkt.dp_Res1 > 0;
  74.  
  75.   /* this *can't* be a symlink... */
  76.   return 0;
  77. }
  78.  
  79. int readlink(const char *path, char *buf, int bufsiz)
  80. {
  81.   struct readlink_vec rv;
  82.   struct stat stb;
  83.   int rc;
  84.   
  85.   /* readlink is buggy in the current fs release (37.26 here), in that
  86.      it reports OBJECT_NOT_FOUND if a file is present but not a 
  87.      symbolic link */
  88.   if (syscall(SYS_lstat, path, &stb) == 0)
  89.     {
  90.       if (S_ISLNK (stb.st_mode))
  91.     {
  92.       rv.buf = alloca(bufsiz);
  93.       rv.bufsize = bufsiz;
  94.   
  95.       rc = __plock ((char *)path, __readlink_func, &rv);
  96.       if (rc <= 0)
  97.         {
  98.           errno = __ioerr_to_errno (IoErr ());
  99.           KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  100.         }
  101.           else
  102.             {
  103.               int len = a2u(NULL, rv.buf);
  104.               char *p = alloca(len);
  105.  
  106.               a2u(p, rv.buf);
  107.               if (p[0] == '.' && p[1] == '/')  /* skip ./ */
  108.               {
  109.                 p += 2;
  110.                 len -= 2;
  111.               }
  112.               rc = (len - 1 < bufsiz ? len - 1 : bufsiz);
  113.               memcpy(buf, p, rc);
  114.               if (rc < bufsiz)
  115.                 buf[rc] = '\0';
  116.             }
  117.       return rc > 0 ? rc : -1;
  118.     }
  119.       else
  120.     {
  121.       errno = EINVAL;
  122.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  123.     }
  124.     }
  125.   /* errno should be set already by lstat() */
  126.   return -1;
  127. }
  128.  
  129. static int a2u(char *buf, char *src)
  130. {
  131.   int len = 0;
  132.  
  133.   if (index(src, ':'))
  134.   {
  135.     if (buf)
  136.       buf[len] = '/';
  137.     len++;
  138.     while (*src != ':')
  139.     {
  140.       if (buf)
  141.         buf[len] = *src;
  142.       len++;
  143.       src++;
  144.     }
  145.     src++;
  146.   }
  147.   else
  148.   {
  149.     if (buf)
  150.       buf[len] = '.';
  151.     len++;
  152.   }
  153.   while (*src)
  154.   {
  155.     if (*src == '/')
  156.     {
  157.       if (buf)
  158.         strcpy(buf + len, "/..");
  159.       len += 3;
  160.       src++;
  161.     }
  162.     else
  163.     {
  164.       if (buf)
  165.         buf[len] = '/';
  166.       len++;
  167.       while (*src && *src != '/')
  168.       {
  169.         if (buf)
  170.           buf[len] = *src;
  171.         src++;
  172.         len++;
  173.       }
  174.       if (*src)
  175.         src++;
  176.     }
  177.   }
  178.   if (buf)
  179.     buf[len] = '\0';
  180.   return len + 1;
  181. }
  182.