Mail Archives: djgpp-workers/1999/03/04/13:11:24
Below are my latest chroot patches. I'm hoping they are complete and
correct.
*** include/libc/root.h.orig Sun Feb 28 14:25:36 1999
--- include/libc/root.h Sun Feb 28 14:28:54 1999
***************
*** 0 ****
--- 1,16 ----
+ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
+ #ifndef __djgpp_libc_root_h
+ #define __djgpp_libc_root_h
+
+ #define ROOT_ENV "ROOT"
+ #define CHROOT_ENV "CHROOT_UNIX"
+
+ extern char __djgpp_root[];
+ extern int __djgpp_root_len;
+
+ int chroot (const char *path);
+
+ char *__delete_root (char *path);
+
+ #endif
+
*** src/libc/compat/unistd/chroot.c.orig Sun Feb 28 14:25:18 1999
--- src/libc/compat/unistd/chroot.c Thu Mar 4 12:17:56 1999
***************
*** 0 ****
--- 1,148 ----
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <limits.h>
+ #include <sys/stat.h>
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <libc/bss.h>
+ #include <libc/root.h>
+
+ static int chroot_bss_count = -1;
+
+ unsigned int __chroot_flags = __CHROOT_UNIX_MODE_FLAG;
+ static unsigned int old_flags;
+
+ char __djgpp_root[PATH_MAX + 1] = { '\0' };
+ int __djgpp_root_len = 0;
+
+
+ int
+ chroot (const char *path)
+ {
+ char buf[PATH_MAX+1];
+ char *to = __djgpp_root;
+ char *from = buf;
+ int unix_emu;
+ int path_len;
+
+ if ((path_len = strlen(path)) > PATH_MAX)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ if (chroot_bss_count != __bss_count)
+ {
+ chroot_bss_count = __bss_count;
+ old_flags = ~0;
+ }
+
+ unix_emu = __chroot_flags & __CHROOT_UNIX_MODE_FLAG;
+
+ /* When not emulating the Unix behavior of chroot,
+ allow a null root to delete the root path. */
+ if (path == NULL || *path == '\0')
+ {
+ if (unix_emu)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+ __djgpp_root[0] = '\0';
+ __djgpp_root_len = 0;
+ setenv(ROOT_ENV, __djgpp_root, 1);
+ return 0;
+ }
+
+ /* When in Unix/restrictive mode, don't allow drive letters
+ in a new root directory after a root directory has been set.
+ Even if the new directory is relative to the root. */
+ if (*path && *(path+1) == ':')
+ {
+ if (unix_emu && __djgpp_root_len > 0)
+ {
+ errno = EACCES;
+ return -1;
+ }
+ _fixpath(path, buf);
+ }
+ else if (*path != '/' && *path != '\\' && __djgpp_root_len > 0)
+ {
+ /* Relative paths are relative to the root, not the cwd. */
+ char path_buf[PATH_MAX+1];
+ path_buf[0] = '/';
+ strcpy(path_buf+1, path);
+ _fixpath(path_buf, buf);
+ }
+ else
+ _fixpath(path, buf);
+
+ if (unix_emu)
+ {
+ /* If a root directory already exists, the new root directory
+ must be relative to the existing root directory.
+ If not, then reject the path. */
+ if (__djgpp_root_len > 0 && *buf != '/')
+ {
+ errno = EACCES;
+ return -1;
+ }
+ }
+
+ /* Make sure the path is valid before
+ making it the new root path. */
+ if (access(buf, D_OK) < 0)
+ return -1;
+
+ /* Copy in the new root path. */
+ if (*buf != '/')
+ __djgpp_root_len = 0;
+ else /* Append to the current root path. */
+ to = __djgpp_root + __djgpp_root_len;
+
+ while (*from)
+ {
+ *to = *from;
+ ++to;
+ ++from;
+ ++__djgpp_root_len;
+ }
+
+ /* Set up environmental variables to be used so child programs
+ created with DJGPP will inherit the root path and mode. */
+ setenv(ROOT_ENV, __djgpp_root, 1);
+
+ if (old_flags != __chroot_flags)
+ {
+ setenv(CHROOT_ENV, (unix_emu ? "Y" : "N"), 1);
+ old_flags = __chroot_flags;
+ }
+
+ return 0;
+ }
+
+
+ /* Delete the root path from an input path.
+ The input path is assumed to have already been canonicalized. */
+
+ char *
+ __delete_root (char *path)
+ {
+ if (__djgpp_root_len > 0 && path[0] != '/')
+ {
+ if (strnicmp (path, __djgpp_root, __djgpp_root_len) == 0
+ && (path[__djgpp_root_len] == '/' || path[__djgpp_root_len] ==
'\0'))
+ {
+ if (path[__djgpp_root_len] == '/')
+ strcpy (path, path + __djgpp_root_len);
+ else
+ {
+ /* path is equal to the root path. */
+ path[0] = '/';
+ path[1] = '\0';
+ }
+ }
+ }
+ return path;
+ }
+
*** src/libc/compat/unistd/fchroot.c.orig Sun Feb 28 14:25:24 1999
--- src/libc/compat/unistd/fchroot.c Wed Mar 3 17:34:36 1999
***************
*** 0 ****
--- 1,17 ----
+ #include <unistd.h>
+ #include <errno.h>
+ #include <libc/root.h>
+
+ int
+ fchroot (int fd)
+ {
+ unsigned int flags = __chroot_flags;
+
+ /* Use &= in case more flags are ever added. */
+ __chroot_flags &= ~__CHROOT_UNIX_MODE_FLAG;
+ chroot (NULL);
+ __chroot_flags = flags;
+
+ return 0;
+ }
+
*** src/libc/dos/io/putpath.c.orig Thu Oct 29 05:24:44 1998
--- src/libc/dos/io/putpath.c Thu Feb 25 14:02:32 1999
***************
*** 3,8 ****
--- 3,9 ----
#include <libc/stubs.h>
#include <libc/dosio.h>
#include <libc/farptrgs.h>
+ #include <libc/root.h>
#include <go32.h>
#include <stdlib.h>
#include <string.h>
***************
*** 49,54 ****
--- 50,66 ----
}
else if (p[5])
path = p + 5;
+ }
+ /* If the path is absolute and a root path is set,
+ then add the root path to the output. */
+ else if (path[0] == '/' && __djgpp_root_len > 0 )
+ {
+ char *root = __djgpp_root;
+ for ( ; *root; root++)
+ {
+ _farnspokeb (o++, *root);
+ space -= 1;
+ }
}
/* collapse multiple slashes to a single slash */
*** src/libc/posix/sys/stat/fixpath.c.orig Sun Dec 13 08:09:46 1998
--- src/libc/posix/sys/stat/fixpath.c Thu Feb 25 14:01:42 1999
***************
*** 13,18 ****
--- 13,19 ----
#include <crt0.h> /* For crt0 flags */
#include <sys/stat.h>
#include <libc/dosio.h>
+ #include <libc/root.h>
static unsigned use_lfn;
***************
*** 73,78 ****
--- 74,80 ----
5. Removing ".." entries in the path (and the directory above them)
6. Adding a drive specification if one wasn't there
7. Converting all slashes to '/'
+ 8. Remove the portion of the path matching the root path
*/
void
_fixpath(const char *in, char *out)
***************
*** 227,232 ****
--- 229,240 ----
}
else if (*op == '\0')
break;
+ }
+
+ /* Remove the portion of the path matching the root path */
+ if (__djgpp_root_len > 0 && out[0] != '/')
+ {
+ __delete_root(out);
}
}
*** src/libc/compat/unistd/chroot.txh.orig Sun Feb 28 14:25:02 1999
--- src/libc/compat/unistd/chroot.txh Thu Mar 4 12:31:42 1999
***************
*** 0 ****
--- 1,104 ----
+ @node chroot, file system
+ @subheading Syntax
+
+ @example
+ #include <unistd.h>
+
+ extern unsigned int __chroot_flags;
+
+ int chroot(const char *new_root_directory);
+ @end example
+
+ @subheading Description
+
+ Causes @var{new_root_directory} to become the root directory, or
+ starting point, for path name searches beginning with @file{/} or
+ @file{\}. The current working directory is unaffected.
+
+ By default, @code{chroot} is set to Unix compatibility or restrictive
+ mode. In this mode, @var{new_root_directory} can be any existing
+ directory. In successive calls, @var{new_root_directory} must exist
and
+ be relative to the current root directory, or else the call fails. The
+ only way to reset the root directory is with a call to @code{fchroot}
+ (@pxref{fchroot}). This mimics the behavior of Unix versions of
+ @code{chroot}.
+
+ The other available mode is Bash compatibility or permissive mode.
In
+ this mode, @var{new_root_directory} must still exist, but it need not
be
+ relative to the current root like in restrictive mode. This mimics the
+ behavior of the @code{SYSROOT} environment variable in the
DJGPP port of
+ Bash 1.14.7.
+
+ To allow a child program to inherit the root directory of its parent,
+ @code{chroot} sets the environment variables @code{ROOT} and
+ @code{CHROOT_UNIX}. If set, @code{ROOT} will contain the root
+ directory. If @var{CHROOT_UNIX} is not set or is set to @samp{Y},
+ @code{chroot} is set to enforce the restrictive Unix behavior. If
+ @code{CHROOT_UNIX} is set to anything other than @samp{Y}, then
+ @code{chroot} is set to allow the permissive behavior.
@code{SYSROOT},
+ an environment variable used by the DJGPP port of Bash 1.14.7, is
+ supported in the interest of backward compatibility but its use is
+ discouraged. If @code{ROOT} is not set, but @code{SYSROOT} is,
then
+ @code{SYSROOT} is used to set the root directory, and
@code{chroot} is
+ set to permissive mode, and @code{CHROOT_UNIX} is ignored.
+
+ The global variable @code{__chroot_flags} can be set to include the
+ following values to control the operation of @code{chroot}:
+
+ @table @code
+
+ @item __CHROOT_UNIX_MODE_FLAG
+
+ If set, @code{chroot} is in Unix compatibility or restrictive mode. If
+ not set, @code{chroot} is in Bash compatibility or permissive mode.
See
+ the above description for how these two modes differ.
+
+ @end table
+
+ @subheading Return Value
+
+ Zero if successful, else nonzero and @code{errno} set if error.
+
+ @subheading Portability
+
+ @port-note The variable @code{__chroot_flags} is DJGPP specific.
+ @portability !ansi, !posix
+
+ @subheading Example
+
+ In our examples, assume 'c:/djgpp' and 'c:/djgpp/bin/gcc.exe' exist.
+
+ An example for Unix compatibility or restrictive mode:
+
+ @example
+ chroot("c:/djgpp");
+
+ /* This call will not succeed. Root will not be changed. */
+ chroot("c:/");
+
+ /* Checks c:/djgpp/bin/gcc.exe */
+ if (access("/bin/gcc.exe", R_OK) == 0)
+ printf("gcc.exe found");
+
+ /* Succeeds because 'c:/djgpp/bin' is relative to 'c:/djgpp'.
+ Passing in '/bin' would have also worked. */
+ chroot("c:/djgpp/bin");
+ @end example
+
+ An example for Bash compatibility or permissive mode:
+
+ @example
+ /* Disable Unix compatibility or restrictive mode. */
+ __chroot_flags = 0;
+
+ chroot("c:/djgpp");
+
+ /* This will succeed since directory need not be relative
+ to 'c:/djgpp' like in the first example. */
+ chroot("c:/");
+
+ /* You can change to any directory on any drive as long
+ as the directory exists. */
+ chroot("d:/windows");
+ @end example
+
*** src/libc/compat/unistd/fchroot.txh.orig Sun Feb 28 14:24:58 1999
--- src/libc/compat/unistd/fchroot.txh Thu Mar 4 12:30:24 1999
***************
*** 0 ****
--- 1,39 ----
+ @node fchroot, file system
+ @subheading Syntax
+
+ @example
+ #include <unistd.h>
+
+ int fchroot(int file_handle);
+ @end example
+
+ @subheading Description
+
+ Clears the root directory set by any previous calls to @xref{chroot}.
+ Because DOS does not allow you to obtain a file handle to a
+ directory, @var{file_handle} is ignored. This does introduce an
+ incompatibility with Unix. However, since @code{fchroot} in Unix
+ is guaranteed to succeed only when changing to the system root,
+ this function will be portable most of the time.
+
+ @subheading Return Value
+
+ Always returns zero for success, unless @var{file_handle} is less
than
+ zero.
+
+ @subheading Portability
+
+ @portability !ansi, !posix
+
+ @subheading Example
+
+ @example
+ chroot("c:/djgpp");
+ if (access("/bin/gcc.exe", R_OK) < 0)
+ fprintf(stderr, "gcc.exe not found");
+
+ fchroot(1);
+
+ if (access("/bin/gcc.exe", R_OK) < 0)
+ fprintf(stderr, "gcc.exe not found");
+ @end example
*** src/libc/posix/unistd/getcwd.c.orig Sat Aug 31 18:09:32 1996
--- src/libc/posix/unistd/getcwd.c Sun Feb 28 14:41:40 1999
***************
*** 13,18 ****
--- 13,19 ----
#include <crt0.h>
#include <libc/farptrgs.h>
#include <libc/dosio.h>
+ #include <libc/root.h>
char *
__getcwd(char *buf, size_t size)
***************
*** 107,112 ****
--- 108,119 ----
__dpmi_int(0x21, &r);
buf[0] = r.h.al + (r.h.al < 26 ? 'a' : 'A');
+
+ /* See if we need to strip the root path set by chroot */
+ if (__djgpp_root_len > '\0')
+ {
+ __delete_root(buf);
+ }
return buf;
}
*** src/libc/crt0/crt1.c.orig Thu Sep 17 05:50:22 1998
--- src/libc/crt0/crt1.c Fri Feb 26 17:51:42 1999
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
***************
*** 189,194 ****
--- 190,196 ----
__crt0_setup_arguments();
_npxsetup(__crt0_argv ? __crt0_argv[0] : __dos_argv0);
_crt0_init_mcount();
+ __crt0_setup_chroot();
__main();
errno = 0; /* ANSI says errno should be zero at program startup */
exit(main(__crt0_argc, __crt0_argv, environ));
*** src/libc/crt0/c1root.c.orig Sun Feb 28 14:08:22 1999
--- src/libc/crt0/c1root.c Thu Mar 4 12:46:52 1999
***************
*** 0 ****
--- 1,69 ----
+ #include <libc/root.h>
+ #include <libc/bss.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <unistd.h>
+
+ /* Here is we check for three environmental variables
+ that may result in a call to chroot():
+ ROOT - the root path. Can be set manually or by chroot().
+ CHROOT_UNIX - Y if chroot is to emulate the restrictive
+ behavior of the Unix implementations.
+ Any other value to select the non-restrictive
+ behavior implemented by Bash 1.147.
+ SYSROOT - Bash 1.147 sets this variable to the directory to
+ use when searching for path names beginning
+ with '/' or '\'. If ROOT is set, this variable
+ is ignored. If ROOT is not set and SYSROOT does
+ contain a path, then chroot() emulates the
+ non-restrictive behavior of Bash 1.147 regardless
+ of the value of CHROOT_UNIX. This variable is checked
+ to maintain backward compatibility with Bash 1.147.
+ Someday, this variable will be completely ignored
+ once a DJGPP port of Bash 2 has been released
+ and is in wide use. */
+
+
+ static int __setup_root_bss_count = 0;
+
+ void
+ __crt0_setup_chroot()
+ {
+ char *root = getenv(ROOT_ENV);
+ char *sysroot = (root ? NULL : getenv("SYSROOT"));
+ char *unix_mode = (!sysroot ? getenv(CHROOT_ENV) : NULL);
+ int ret_code;
+
+ if (unix_mode)
+ {
+ if (*unix_mode == 'Y' || *unix_mode == 'y')
+ __chroot_flags = __CHROOT_UNIX_MODE_FLAG;
+ else
+ __chroot_flags = 0;
+ }
+ else if (sysroot)
+ __chroot_flags = 0;
+
+ if (sysroot)
+ root = sysroot;
+
+ if (root)
+ {
+ __setup_root_bss_count = __bss_count;
+ /* Aborts if call to chroot() fails. */
+ if (chroot(root) < 0)
+ {
+ fprintf(stderr, "Call to chroot('%s') failed in
__crt0_setup_chroot()\n", root);
+ abort();
+ }
+ }
+ /* If restarting, and ROOT or SYSROOT was not defined,
+ then reset _djgpp_root to no root. */
+ else if (__setup_root_bss_count != __bss_count)
+ {
+ __djgpp_root[0] = '\0';
+ __djgpp_root_len = 0;
+ __setup_root_bss_count = __bss_count;
+ }
+ }
+
---
Mark Elbrecht
snowball3 AT usa DOT net http://members.xoom.com/snowball3/
- Raw text -