home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / library / rcs / __plock.c,v < prev    next >
Encoding:
Text File  |  1992-08-09  |  18.2 KB  |  726 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.08.09.20.38.34;    author amiga;    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. @lowlevel path expander, used by all functions requiring a path name
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @change to use 2.x header files by default
  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: __plock.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
  49.  *
  50.  *  $Log: __plock.c,v $
  51.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  52.  *  Initial revision
  53.  *
  54.  */
  55.  
  56. /* 20-jan-92    -mw-    revamped to emulate GetDeviceProc() under 1.3
  57.  *            new way to find out whether IsFileSystem(name)
  58.  * 14-mar-92    -mw-    limited /sys -> sys: mapping. `/' is now treated
  59.  *            as undefined path, to be compatible to a later
  60.  *            version, where it will be a virtual directory
  61.  *            of devices and logicals
  62.  */
  63.  
  64. /*
  65.  * Lock() and LLock() emulation. Takes care of expanding paths that contain
  66.  * symlinks. 
  67.  * Call __plock() if you need a lock to the parent directory as used in
  68.  * other packets, that way you always get the "right" thing
  69.  */
  70.  
  71. #define KERNEL
  72. #include "ixemul.h"
  73. #include <stdlib.h>
  74. #include <string.h>
  75.  
  76. #undef DEBUG
  77.  
  78. #ifdef DEBUG
  79. #define DP(a) kprintf a
  80. #else
  81. #define DP(a)
  82. #endif
  83.  
  84. /* don't need async packets in here, no shared file packets are in use */
  85. #define __srwport (u.u_sync_mp)
  86.  
  87. #if __GNUC__ != 2
  88. #define alloca __builtin_alloca
  89. #endif
  90.  
  91. #ifndef ACTION_READ_LINK
  92. #define ACTION_READ_LINK 1024
  93. #endif
  94.  
  95. #ifndef ACTION_IS_FILESYSTEM
  96. #define ACTION_IS_FILESYSTEM 1027
  97. #endif
  98.  
  99.  
  100. #ifndef ERROR_IS_SOFT_LINK
  101. #define ERROR_IS_SOFT_LINK  233
  102. #endif
  103.  
  104. #ifndef DVPF_ASSIGN
  105. /* structure return by GetDeviceProc() */
  106. struct DevProc {
  107.     struct MsgPort *dvp_Port;
  108.     BPTR        dvp_Lock;
  109.     ULONG        dvp_Flags;
  110.     struct DosList *dvp_DevNode;    /* DON'T TOUCH OR USE! */
  111. };
  112.  
  113. /* definitions for dvp_Flags */
  114. #define DVPB_UNLOCK    0
  115. #define DVPF_UNLOCK    (1L << DVPB_UNLOCK)
  116. #define DVPB_ASSIGN    1
  117. #define DVPF_ASSIGN    (1L << DVPB_ASSIGN)
  118.  
  119. #define BASE_EXT_DECL
  120. #define BASE_PAR_DECL    
  121. #define BASE_PAR_DECL0    
  122. #define BASE_NAME    ix.ix_dos_base
  123. __inline static struct DevProc* GetDeviceProc(BASE_PAR_DECL UBYTE* name, struct DevProc* dp)
  124. {
  125.     BASE_EXT_DECL
  126.     register struct DevProc* res __asm("d0");
  127.     register void *a6 __asm ("a6");
  128.     register UBYTE* d1 __asm("d1");
  129.     register struct DevProc* d2 __asm("d2");
  130.  
  131.     a6 = BASE_NAME;
  132.     d1 = name;
  133.     d2 = dp;
  134.     __asm volatile ("
  135.     jsr a6@@(-0x282)"
  136.     : "=r" (res)
  137.     : "r" (a6), "r" (d1), "r" (d2)
  138.     : "d0", "d1", "a0", "a1", "d2");
  139.     *(char*)d2=*(char *)d2;
  140.     return res;
  141. }
  142. __inline static void FreeDeviceProc(BASE_PAR_DECL struct DevProc* dp)
  143. {
  144.     BASE_EXT_DECL
  145.     register void *a6 __asm ("a6");
  146.     register struct DevProc* d1 __asm("d1");
  147.  
  148.     a6 = BASE_NAME;
  149.     d1 = dp;
  150.     __asm volatile ("
  151.     jsr a6@@(-0x288)"
  152.     : /* no output */
  153.     : "r" (a6), "r" (d1)
  154.     : "d0", "d1", "a0", "a1");
  155.      *(char*)d1=*(char *)d1;    
  156. }
  157. #endif
  158.  
  159. static struct DevProc    *get_device_proc (char *, struct DevProc *, int *);
  160. static void         free_device_proc (struct DevProc *);
  161. static int        unslashify (char *);
  162.  
  163. extern int _dos20;
  164.  
  165. BPTR
  166. __plock (char *file_name, int (*last_func)(), void *last_arg)
  167. {
  168.   BPTR parent_lock;
  169.   struct MsgPort *handler;
  170.   struct StandardPacket *sp;
  171.   unsigned char *bstr;
  172.   char *sep, *next, *cp;
  173.   int len;
  174.   /* true when we're processing the last element of name */
  175.   int is_last;
  176.   /* true after first pass, we should unlock all locks except the one
  177.    * we get as a sideeffect of DeviceProc */
  178.   int unlock_parent;
  179.   int link_levels;
  180.   int no_error;
  181.   BPTR result;
  182.   int res_res2;
  183.   int omask;
  184.   int split_name;
  185.   struct DevProc *dp;
  186.   char *orig_name, *name;
  187.  
  188.   DP(("__plock: file_name = %s, last_func = $%lx\n", 
  189.       file_name ? file_name : "(none)", last_func));
  190.  
  191.   /* ``fix'' until I find the real problem in pdksh.. */
  192.   if (! file_name)
  193.     return 0;
  194.  
  195.   /* need to operate on a backup of the passed name, so I can do
  196.    * /sys -> sys: conversion in place */
  197.   name = alloca (strlen (file_name) + 1);
  198.   strcpy (name, file_name);
  199.   orig_name = name;
  200.  
  201.   /* now get a LONG aligned packet */
  202.   sp = alloca (sizeof(*sp)+2);
  203.   sp = LONG_ALIGN (sp);
  204.   __init_std_packet(sp);
  205.  
  206.   /* allocate one BSTR-buffer. A length of 255 is enough, since a bstr
  207.    * can't address any more ;-) */
  208.   bstr = alloca (256 + 2);
  209.   bstr = LONG_ALIGN (bstr);
  210.   
  211.   /* NOTE: although we don't use any DOS calls here, we have to block
  212.    * any signals, since the locks we obtain in this function have to
  213.    * be freed before anything else can be done. This function is
  214.    * *not* reentrant in the sense that it can be interrupted without
  215.    * being finished */
  216.   omask = syscall (SYS_sigsetmask, ~0);
  217.  
  218.   dp = 0;
  219.  
  220. retry_multi_assign:
  221.  
  222.   name = orig_name;
  223.   if (ix.ix_translate_slash && unslashify (name) < 0)
  224.     {
  225.       result = 0;
  226.       res_res2 = ERROR_OBJECT_NOT_FOUND;
  227.       dp = 0;
  228.       goto do_return;
  229.     }
  230.  
  231.   if (! strcmp (name, "*") || ! strcasecmp (name, "console:"))
  232.     {
  233.       handler = (struct MsgPort *)(((struct Process *)FindTask (0))->pr_ConsoleTask);
  234.       parent_lock = 0;
  235.       DP(("__plock: console override, handler $%lx.\n", handler));
  236.       name = "*"; /* supports console: under 1.3 */
  237.       if (dp) free_device_proc (dp);
  238.       split_name = 0;
  239.       dp = 0;
  240.     }
  241.   else if (! strcasecmp (name, "nil:") || ! strcasecmp (name, "/nil") ||
  242.       ! strcmp (name, "/dev/null") || ! strcmp (name, "dev:null"))
  243.     {
  244.     result = 0;
  245.         res_res2 = 4242;    /* special special ;-)))) */
  246.         dp = 0;
  247.         goto do_return;
  248.     }
  249.   else
  250.     {
  251.       dp = get_device_proc (name, dp, &split_name);
  252.       DP(("__plock: gdp(%s) -> $%lx",name,dp));
  253.  
  254.       handler = dp ? dp->dvp_Port : 0;
  255.       parent_lock = dp ? dp->dvp_Lock : 0;
  256.       if (handler)
  257.         DP(("  handler = $%lx, parent_lock = $%lx, is_fs = %ld\n", handler, parent_lock, split_name));
  258.       else
  259.         DP(("\n"));
  260.     }
  261.  
  262.   is_last = 0;
  263.   unlock_parent = 0;
  264.   link_levels = 0;
  265.   result = 0;
  266.  
  267.   if (! handler) 
  268.     {
  269.       res_res2 = ERROR_OBJECT_NOT_FOUND;
  270.       goto do_return;
  271.     }
  272.  
  273.   link_levels = 0;
  274.  
  275.   /* this seems logical, doesn't it? don't know ;-)) */
  276.   sep = index (name, ':');
  277.   if (sep) name = sep+1;
  278.  
  279.   do
  280.     {
  281. DP(("__plock: solving for %s.\n", name));
  282.  
  283.       if (split_name)
  284.         {
  285.       /* fetch the first part of "name", thus stopping at either a : or a / 
  286.        * next points at the start of the next directory component to be
  287.        * processed in the next run
  288.        */
  289.  
  290.       sep = index (name, ':');
  291.       if (sep) 
  292.         {
  293.           sep++; /* the : is part of the filename */
  294.           next = sep;
  295.         }
  296.       else
  297.         {
  298.           sep = index (name, '/');
  299.           
  300.           /* map foo/bar/ into foo/bar, but keep foo/bar// */
  301.           if (sep && sep[1]==0)
  302.             {
  303.               is_last = 1;
  304.               next = sep;
  305.             }
  306.           else if (! sep)
  307.             {
  308.               sep = name + strlen (name);
  309.               next = sep;
  310.               is_last = 1;
  311.             }
  312.           else
  313.             {
  314.               if (ix.ix_translate_slash)
  315.             for (next = sep + 1; *next == '/'; next ++) ;
  316.           else
  317.             next = sep + 1;
  318.         
  319.               /* if the slash is the first character, it means "parent",
  320.                * so we have to pass it literally to Lock() */
  321.               if (sep == name) sep = next;
  322.             }
  323.         }
  324.     }
  325.       else
  326.     {
  327.       sep = name + strlen (name);
  328.       is_last = 1;
  329.     }
  330.  
  331.       len = sep - name;
  332.       if (len) bcopy (name, bstr + 1, len);
  333.       *bstr = len;
  334.  
  335.       if (ix.ix_translate_dots)
  336.     {
  337.           /* turn a ".." into a "/", and a "." into a "" */
  338.  
  339.       if (bcmp (bstr, "\2..", 3) == 0)
  340.         {
  341.           bstr[0] = 1; bstr[1] = '/';
  342.         }
  343.       else if (bcmp (bstr, "\1.", 2) == 0)
  344.         bstr[0] = 0;
  345.     }
  346.  
  347.       do
  348.     {
  349.           sp->sp_Pkt.dp_Port = __srwport;
  350.       if (! is_last)
  351.         {
  352.               sp->sp_Pkt.dp_Type = ACTION_LOCATE_OBJECT;
  353.               sp->sp_Pkt.dp_Arg1 = parent_lock;
  354.               sp->sp_Pkt.dp_Arg2 = CTOBPTR(bstr);
  355.               sp->sp_Pkt.dp_Arg3 = ACCESS_READ;
  356.  
  357.               PutPacket(handler, sp);
  358.               __wait_sync_packet(sp);
  359.  
  360.           no_error = sp->sp_Pkt.dp_Res1 > 0;
  361.         }
  362.       else
  363.         if (! (*last_func)(sp, handler, parent_lock, CTOBPTR (bstr),
  364.                                last_arg, &no_error)) break;
  365.  
  366.       /* if no error, fine */
  367.           if (no_error) break;
  368.  
  369.       /* else check whether ordinary error or really symlink */
  370.           if (sp->sp_Pkt.dp_Res2 != ERROR_IS_SOFT_LINK) break;
  371.  
  372.       /* read the link. temporarily use our bstr as a cstr, thus setting
  373.            * a terminating zero byte and skipping the length byte */
  374.       bstr[*bstr + 1] = 0;
  375.  
  376.           sp->sp_Pkt.dp_Port = __srwport;
  377.           sp->sp_Pkt.dp_Type = ACTION_READ_LINK;
  378.           sp->sp_Pkt.dp_Arg1 = parent_lock;
  379.           sp->sp_Pkt.dp_Arg2 = (long) (bstr + 1); /* read as cstr */
  380.           sp->sp_Pkt.dp_Arg3 = (long) (bstr + 1); /* write as cstr, same place */
  381.           sp->sp_Pkt.dp_Arg4 = 255; /* what a BSTR can address */
  382.  
  383.           PutPacket(handler, sp);
  384.           __wait_sync_packet(sp);
  385.  
  386.       /* error (no matter which...) couldn't read the link */
  387.       if (sp->sp_Pkt.dp_Res1 <= 0)
  388.         {
  389.           /* this is our error-"lock", so make sure it is really zero */
  390.           sp->sp_Pkt.dp_Res1 = 0;
  391.           break;
  392.             }
  393.  
  394.       /* oky, new name. Set up as bstr and retry to lock it */
  395.       *bstr = sp->sp_Pkt.dp_Res1;
  396.  
  397.       /* if the read name is absolute, we may have to change the
  398.        * handler and the parent lock. Check for this */
  399.       bstr[*bstr + 1] = 0;
  400.       
  401.       /* this isn't enabled by default, because it makes normal dos calls
  402.        * fail miserably */
  403.       if (ix.ix_translate_symlinks && unslashify (bstr + 1) < 0)
  404.         {
  405.           sp->sp_Pkt.dp_Res1 = 0;
  406.           sp->sp_Pkt.dp_Res2 = ERROR_OBJECT_NOT_FOUND;
  407.           break;
  408.         }
  409.       
  410.       if (cp = index ((char *)bstr + 1, ':'))
  411.         {
  412.               if (unlock_parent)
  413.             {
  414.                   sp->sp_Pkt.dp_Port = __srwport;
  415.                   sp->sp_Pkt.dp_Type = ACTION_FREE_LOCK;
  416.                   sp->sp_Pkt.dp_Arg1 = parent_lock;
  417.  
  418.                   PutPacket(handler, sp);
  419.                   __wait_sync_packet(sp);
  420.             }
  421.  
  422.           /* if this is ":foobar", then the handler stays the same, and the
  423.            * parent_lock gets zero. Don't need get_device_proc() to find
  424.            * this out ;-) */
  425.           if (cp == (char *)bstr+1)
  426.         parent_lock = 0;
  427.           else
  428.           /*
  429.            * NOTE: Multiassigns are currently only supported as the first
  430.            *       part of a path name. I don't like the idea of setting up
  431.            *       another recursion level here just to parse them...
  432.            *
  433.            * This approach also makes symbolic links to non-fs devices
  434.            * limited, which is bad. I'll HAVE to think something up
  435.            * (so you can't for example have dev:tty -> con:0/0/640/100/tty)
  436.            */
  437.               handler = DeviceProc (bstr + 1);    /* XXX fix !!! */
  438.               parent_lock = IoErr ();
  439.               unlock_parent = 0;
  440.               
  441.               if (! handler)
  442.                 {
  443.                   /* interesting bug.. long not noticed... */
  444.  
  445.           sp->sp_Pkt.dp_Res1 = 0;
  446.           if (! strcasecmp (bstr + 1, "nil:"))
  447.             sp->sp_Pkt.dp_Res2 = 4242;
  448.           else
  449.             sp->sp_Pkt.dp_Res2 = ERROR_OBJECT_NOT_FOUND;
  450.           break;
  451.         }
  452.         }
  453.  
  454.       ++link_levels;
  455.     }
  456.       while (link_levels < MAXSYMLINKS);
  457.  
  458.       if (link_levels == MAXSYMLINKS)
  459.     {
  460.       result = 0;
  461.       res_res2 = ERROR_TOO_MANY_LEVELS;
  462.     }
  463.       else
  464.     {
  465.       result = sp->sp_Pkt.dp_Res1;
  466.       res_res2 = sp->sp_Pkt.dp_Res2;
  467.     }
  468.  
  469.       if (unlock_parent)
  470.     {
  471.           sp->sp_Pkt.dp_Port = __srwport;
  472.           sp->sp_Pkt.dp_Type = ACTION_FREE_LOCK;
  473.           sp->sp_Pkt.dp_Arg1 = parent_lock;
  474.  
  475.           PutPacket(handler, sp);
  476.           __wait_sync_packet(sp);
  477.     }
  478.       else
  479.     unlock_parent = 1;
  480.  
  481.       parent_lock = result;
  482.       name = next;
  483.     }
  484.   while (no_error && ! is_last);
  485.  
  486.   /* yes I know it's ugly ... */
  487.   if (!no_error && res_res2 == ERROR_OBJECT_NOT_FOUND 
  488.       && dp && (dp->dvp_Flags & DVPF_ASSIGN))
  489.     goto retry_multi_assign;
  490.  
  491. do_return:
  492.   free_device_proc (dp);
  493.  
  494.   /* set up Result2 so that the IoErr() works */
  495.   ((struct Process *)FindTask (0))->pr_Result2 = res_res2;
  496.  
  497.   syscall (SYS_sigsetmask, omask);
  498.  
  499. DP(("__plock: returning %ld, res2 = %ld.\n", result, res_res2));
  500.  
  501.   return result;
  502. }
  503.  
  504. /*
  505.  * this is somewhat similar to DeviceProc(), but with the difference that it's
  506.  * strictly passive, it won't start the handler, if it doesn't exist. This is
  507.  * vital to be able to deal with stubborn console handlers, that don't answer
  508.  * packets until they're really open..
  509.  * Returns:
  510.  *    HAN_UNDEF    device doesn't exist
  511.  *    HAN_CLONE_DEV    device exists, handler zero
  512.  *    HAN_FS_DEV    device exists, handler non-zero
  513.  *    HAN_NOT_A_DEV    exists, but is not a device
  514.  */
  515.  
  516. #define HAN_UNDEF    0
  517. #define HAN_CLONE_DEV    1
  518. #define HAN_FS_DEV    2
  519. #define    HAN_NOT_A_DEV    3
  520.  
  521. static int
  522. find_handler (char *bstr)
  523. {
  524.   struct DosLibrary *dl;
  525.   struct RootNode *rn;
  526.   struct DosInfo *di;
  527.   struct DevInfo *dv;
  528.   extern struct ixemul_base *ixemulbase;
  529.   int res = HAN_UNDEF;
  530.   
  531.   /* could probably use less drastic measures under 2.0... */
  532.   Forbid ();
  533.   dl = (struct DosLibrary *) ixemulbase->ix_dos_base;
  534.   rn = (struct RootNode *) dl->dl_Root;
  535.   di = BTOCPTR (rn->rn_Info);
  536.   for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  537.     {
  538. #if 0
  539. /* quite verbose output... */
  540.       {
  541.         char buf[255];
  542.         
  543.         bcopy (BTOCPTR (dv->dvi_Name)+1, buf, *(char *)BTOCPTR (dv->dvi_Name));
  544.         buf[*(char *)BTOCPTR (dv->dvi_Name)] = 0;
  545.         DP(("\t%s(%ld,$%lx)", buf, dv->dvi_Type, dv->dvi_Task));
  546.       }
  547. #endif
  548.  
  549.       if (! strncasecmp (bstr, BTOCPTR (dv->dvi_Name), bstr[0]+1))
  550.         {
  551.           if (dv->dvi_Type == DLT_DEVICE)
  552.             res = dv->dvi_Task ? HAN_FS_DEV : HAN_CLONE_DEV;
  553.           else
  554.         res = HAN_NOT_A_DEV;
  555.       break;
  556.     }
  557.     }
  558.   Permit ();
  559. /*  DP(("\n")); */
  560.   return res;
  561. }
  562.  
  563. /*
  564.  * feels very much like GetDeviceProc(), but works under 1.3 as well. Under
  565.  * 2.0, we're using the dos-library GetDeviceProc(), under 1.3 that is
  566.  * emulated with own structures.
  567.  * is_fs is filled out with a best guess approach, since we can't use the
  568.  * proper packet on a handler that isn't yet fully operating (as after just
  569.  * calling DevProc)
  570.  * if calling with prev!=0, is_fs is not touched.
  571.  */
  572.  
  573. static struct DevProc *
  574. get_device_proc (char *name, struct DevProc *prev, int *is_fs)
  575. {
  576.   char *cp, *f;
  577.   int len;
  578.   struct DevProc *dp;
  579.   int han = HAN_UNDEF;
  580.  
  581.   if (! prev)
  582.     {
  583.       /* have to prove the oposite */
  584.       *is_fs = 1;
  585.  
  586.       cp = index (name, ':');
  587.       if (cp && cp != name)    /* ":..." has to be a filesystem */
  588.         {
  589.           len = cp - name;
  590.           f = alloca (len + 1);
  591.           f[0] = len;
  592.           bcopy (name, f + 1, len);
  593.  
  594.           /* try to find it */
  595.           han = find_handler (f);
  596.  
  597. DP(("  find_handler(%s) = %ld\n", name, han));
  598.  
  599.       /* this might be wrong, we'll know more after GetDeviceProc() */
  600.           if (han == HAN_CLONE_DEV) 
  601.             *is_fs = 0;
  602.         }
  603.     }
  604.   else
  605.     if (! _dos20)
  606.       {
  607.     /* 1.3 doesn't support multiassigns, and this would be the only reason
  608.      * to call here more than once. */
  609.     kfree (prev);
  610.     return 0;
  611.       }
  612.  
  613.   if (_dos20)
  614.     dp = GetDeviceProc (name, prev);  
  615.   else
  616.     {
  617.       dp = (struct DevProc *) kmalloc (sizeof (*dp));
  618.       dp->dvp_Port = DeviceProc (name);
  619.       dp->dvp_Lock = IoErr ();
  620.       dp->dvp_Flags = 0;    /* just don't set DVPF_ASSIGN ;-)) */
  621.       dp->dvp_DevNode = 0;    /* is private anyway */
  622.     }
  623.  
  624.   /* second approach to verify, if a handler probably is a file system or not.
  625.    * If the device is a filesystem, but didn't contain a volume before, then
  626.    * the GetDeviceProc() call will have popped up the `please insert a disk'
  627.    * requester. If the user obeyed, the handler will now exist. On the other
  628.    * hand, if the device really is a clone device, it will still be one (ie. have
  629.    * its task field zero), so check the device list again. */
  630.  
  631.   /* only for possible clone devices */
  632.   if (han == HAN_CLONE_DEV)
  633.     *is_fs = find_handler (f) != HAN_CLONE_DEV;
  634.   
  635.   return dp;
  636. }
  637.  
  638. static void
  639. free_device_proc (struct DevProc *dp)
  640. {
  641.   if (_dos20)
  642.     FreeDeviceProc (dp);
  643.   else
  644.     kfree (dp);
  645. }
  646.  
  647.  
  648. static int
  649. unslashify (char *name)
  650. {
  651.   char *oname = name;
  652.  
  653.   /* if we're here, make sure to return every attempt to use a colon inside
  654.    * a filename as an error. I could at least imagine, that it would be
  655.    * possible for the user to actually generate a file with colons in its
  656.    * name, but he would probably not be able to get rid of it again... */
  657.   if (index (name, ':'))
  658.     return ix.ix_force_translation ? -1 : 0;
  659.  
  660.   while (oname[0] == '/' && oname[1] == '/')
  661.     oname++;
  662.  
  663.   /* don't (!) use strcpy () here, this is an overlapping copy ! */
  664.   if (oname > name)
  665.     bcopy (oname, name, strlen (oname) + 1);
  666.     
  667.   /* This is marked as error, so that the user gets used to use `..' instead of
  668.    * `/' to really mean `parent directory', *iff* he/she enabled ix slash 
  669.    * translation (this function is only called if slash translation is enabled) */
  670.   if (name[0] == '/' && name[1] == 0)
  671.     return ix.ix_force_translation ? -1 : 0;
  672.  
  673.   if (name[0] == '/')
  674.     {
  675.       /* get the delimiter */
  676.       char *cp = index (name + 1, '/');
  677.       int shift = 0;
  678.  
  679.       /* if there is a separating (and not terminating) slash, shift a bit ;-) */
  680.       if (cp)
  681.     while (*cp == '/')
  682.           {
  683.             shift ++;
  684.         cp ++;
  685.       }
  686.  
  687.       /* is it a terminator (then discard it) or a separator ? */
  688.       if (! cp || !*cp)
  689.         {
  690.       /* terminator */
  691.           cp = name + strlen (name);
  692.           bcopy (name + 1, name, cp - name);
  693.           cp[-1-shift] = ':';
  694.           cp[-shift] = 0;
  695.     }
  696.       else
  697.     {
  698.       /* separator */
  699.       bcopy (name + 1, name, strlen (name) + 1);
  700.       cp --;
  701.       bcopy (cp, cp - (shift - 1), strlen (cp) + 1);
  702.       cp[-shift] = ':';
  703.     }
  704.     }
  705.  
  706.   return 0;
  707. }
  708. @
  709.  
  710.  
  711. 1.1
  712. log
  713. @Initial revision
  714. @
  715. text
  716. @d19 1
  717. a19 1
  718.  *  $Id$
  719. d21 4
  720. a24 1
  721.  *  $Log$
  722. a88 1
  723. #endif
  724. d128 1
  725. @
  726.