home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / library / chdir.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  4KB  |  186 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.  
  20. #define _KERNEL
  21. #include "ixemul.h"
  22. #include "kprintf.h"
  23.  
  24. /* this one is for Mike B. Smith ;-) */
  25.  
  26. void set_dir_name_from_lock(BPTR lock)
  27. {
  28.   char *buf = (char *) kmalloc (MAXPATHLEN);
  29.  
  30.   if (buf)
  31.     {
  32.       /* NOTE: This shortcuts any symlinks. But then, Unix does the
  33.        *       same, and a shell that wants to be smart about symlinks,
  34.        *       has to track chdir()s itself as well */
  35.       if (NameFromLock (lock, buf, MAXPATHLEN))
  36.         SetCurrentDirName (buf);
  37.       kfree (buf);
  38.     }
  39. }
  40.  
  41. /*
  42.  * Checks if pathname "name1" is above
  43.  * "name" in directory structure.
  44.  * Lock()/Unlock() are used instead of __lock/__unlock
  45.  * because this routine seems to loop if name2 is a subdir of name1
  46.  */
  47. static short
  48. dirisparent (char *name1, char *name2) {
  49.     short ret = 0;
  50.     BPTR lock1;
  51.  
  52.     lock1 = Lock (name1, SHARED_LOCK);
  53.     if (lock1) {
  54.     BPTR lock2;
  55.  
  56.     lock2 = Lock (name2, SHARED_LOCK);
  57.     if (lock2) {
  58.  
  59.         switch (SameLock (lock1, lock2)) {
  60.  
  61.         case LOCK_DIFFERENT:
  62.         break;
  63.  
  64.         case LOCK_SAME:
  65.             ret = 2;
  66.         break;
  67.  
  68.         case LOCK_SAME_VOLUME:
  69.         {
  70.             BPTR l;
  71.  
  72.             while (lock2) {
  73.             l = lock2;
  74.             lock2 = ParentDir (l);
  75.             UnLock (l);
  76.             if (SameLock (lock1, lock2) == LOCK_SAME) {
  77.                 ret = 1;
  78.                 break;
  79.             }
  80.             }
  81.             break;
  82.         }
  83.         }
  84.         UnLock (lock2);
  85.     }
  86.     UnLock (lock1);
  87.     }
  88.     return ret;
  89. }
  90.  
  91. /* if we change our directory, we have to remember the original cd, when
  92.  * the process was started, because we're not allowed to unlock this
  93.  * lock, since we didn't obtain it. */
  94.  
  95. int chdir (char *path)
  96. {
  97.   BPTR oldlock, newlock;
  98.   int error = 0;
  99.   int omask;
  100.   struct stat stb;
  101.   /* Sigh... CurrentDir() is a DOS-library function, it would probably be
  102.    * ok to just use pr_CurrentDir, but alas, this way we're conformant to
  103.    * programming style guidelines, but we pay the overhead of locking dosbase
  104.    */
  105.  
  106.   /* chdir("/") with u.u_root_directory set, chdir's to root directory */
  107.   if (!strcmp("/",path) && *u.u_root_directory)
  108.     path = u.u_root_directory;
  109.  
  110.   if (syscall (SYS_stat, path, &stb) == 0 && !(stb.st_mode&S_IFDIR))
  111.   {
  112.     errno = ENOTDIR;
  113.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  114.     return -1;
  115.   }
  116.  
  117.   omask = syscall (SYS_sigsetmask, ~0);
  118.  
  119.   newlock = __lock (path, ACCESS_READ);
  120.  
  121.   if (newlock == NULL && IoErr() == 6262)
  122.     {
  123.       u.u_is_root = 1;
  124.       SetCurrentDirName("/");
  125.       syscall (SYS_sigsetmask, omask);
  126.       return 0;
  127.     }
  128.   else if (newlock)
  129.     {
  130.       /* chroot() support - don't do a chdir if the path
  131.        * is a parent directory of the root directory
  132.        */
  133.       if (*u.u_root_directory) {
  134.     char dir[MAXPATHLEN];
  135.  
  136.     if (NameFromLock (newlock, dir, MAXPATHLEN)) {
  137.       if (dirisparent(dir,u.u_root_directory) == 1) {
  138.         errno = EACCES;
  139.         goto chdirerr;
  140.       }
  141.     }
  142.     else {
  143.       errno = __ioerr_to_errno (IoErr ());
  144.       goto chdirerr;
  145.     }
  146.       }
  147.  
  148.       u.u_is_root = 0;
  149.       oldlock = CurrentDir (newlock);
  150.  
  151.       if (u.u_startup_cd == (BPTR)-1)
  152.         u.u_startup_cd = oldlock;
  153.       else
  154.         __unlock (oldlock);
  155.  
  156.       set_dir_name_from_lock(newlock);
  157.  
  158.       syscall (SYS_sigsetmask, omask);
  159.       return 0;
  160.     }
  161.   error = __ioerr_to_errno (IoErr ());
  162.  
  163. chdirerr:
  164.   syscall (SYS_sigsetmask, omask);
  165.   errno = error;
  166.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  167.   return -1;
  168. }
  169.  
  170. /* change the "root" directory to dir */
  171. int chroot(char *dir) {
  172.     int retval;
  173.  
  174.     retval = chdir(dir);
  175.  
  176.     if (retval == 0) {
  177.     BPTR rootlock = __lock(dir,ACCESS_READ);
  178.     if (rootlock)
  179.         NameFromLock(rootlock,u.u_root_directory,MAXPATHLEN);
  180.     else
  181.         retval = -1;
  182.     __unlock(rootlock);
  183.     }
  184.     return retval;
  185. }
  186.