6910249 lx brand should emulate *at(2) POSIX.1-2008 syscalls
authorEdward Pilatowicz <Edward.Pilatowicz@Sun.COM>
Wed Dec 16 18:25:17 2009 -0800 (2 months ago)
changeset 11338e8c975bf2038
parent 113371f8fe42c7b83
child 1133960327fc5209b
6910249 lx brand should emulate *at(2) POSIX.1-2008 syscalls
Contributed by James Lee <jbit@jbit.net>
usr/src/lib/brand/lx/lx_brand/common/file.c
usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
usr/src/lib/brand/lx/lx_brand/common/misc.c
usr/src/lib/brand/lx/lx_brand/common/open.c
usr/src/lib/brand/lx/lx_brand/common/stat.c
usr/src/lib/brand/lx/lx_brand/sys/lx_fcntl.h
usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h
usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
       1 --- a/usr/src/lib/brand/lx/lx_brand/common/file.c	Wed Dec 16 16:39:00 2009 -0800
       2 +++ b/usr/src/lib/brand/lx/lx_brand/common/file.c	Wed Dec 16 18:25:17 2009 -0800
       3 @@ -20,11 +20,9 @@
       4   */
       5  
       6  /*
       7 - * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
       8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
       9   * Use is subject to license terms.
      10   */
      11 -
      12 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
      13  
      14  #include <sys/fstyp.h>
      15  #include <sys/fsid.h>
      16 @@ -44,6 +42,7 @@
      17  #include <sys/lx_types.h>
      18  #include <sys/lx_debug.h>
      19  #include <sys/lx_misc.h>
      20 +#include <sys/lx_fcntl.h>
      21  
      22  static int
      23  install_checkpath(uintptr_t p1)
      24 @@ -67,6 +66,45 @@
      25  	errno = saved_errno;
      26  	return (-errno);
      27  }
      28 +
      29 +/*
      30 + * Convert linux LX_AT_* flags to solaris AT_* flags, while verifying allowed
      31 + * flags have been passed. This also allows EACCESS/REMOVEDIR to be translated
      32 + * correctly since on linux they have the same value.
      33 + */
      34 +int
      35 +ltos_at_flag(int lflag, int allow)
      36 +{
      37 +	int sflag = 0;
      38 +
      39 +	if ((lflag & LX_AT_EACCESS) && (allow & AT_EACCESS)) {
      40 +		lflag &= ~LX_AT_EACCESS;
      41 +		sflag |= AT_EACCESS;
      42 +	}
      43 +
      44 +	if ((lflag & LX_AT_REMOVEDIR) && (allow & AT_REMOVEDIR)) {
      45 +		lflag &= ~LX_AT_REMOVEDIR;
      46 +		sflag |= AT_REMOVEDIR;
      47 +	}
      48 +
      49 +	if ((lflag & LX_AT_SYMLINK_NOFOLLOW) && (allow & AT_SYMLINK_NOFOLLOW)) {
      50 +		lflag &= ~LX_AT_SYMLINK_NOFOLLOW;
      51 +		sflag |= AT_SYMLINK_NOFOLLOW;
      52 +	}
      53 +
      54 +	/* right now solaris doesn't have a _FOLLOW flag, so use a fake one */
      55 +	if ((lflag & LX_AT_SYMLINK_FOLLOW) && (allow & LX_AT_SYMLINK_FOLLOW)) {
      56 +		lflag &= ~LX_AT_SYMLINK_FOLLOW;
      57 +		sflag |= LX_AT_SYMLINK_FOLLOW;
      58 +	}
      59 +
      60 +	/* if flag is not zero than some flags did not hit the above code */
      61 +	if (lflag)
      62 +		return (-EINVAL);
      63 +
      64 +	return (sflag);
      65 +}
      66 +
      67  
      68  /*
      69   * Miscellaneous file-related system calls.
      70 @@ -167,6 +205,31 @@
      71  		return (-EISDIR);
      72  
      73  	return (unlink(pathname) ? -errno : 0);
      74 +}
      75 +
      76 +int
      77 +lx_unlinkat(uintptr_t ext1, uintptr_t p1, uintptr_t p2)
      78 +{
      79 +	int atfd = (int)ext1;
      80 +	char *pathname = (char *)p1;
      81 +	int flag = (int)p2;
      82 +	struct stat64 statbuf;
      83 +
      84 +	if (atfd == LX_AT_FDCWD)
      85 +		atfd = AT_FDCWD;
      86 +
      87 +	flag = ltos_at_flag(flag, AT_REMOVEDIR);
      88 +	if (flag < 0)
      89 +		return (-EINVAL);
      90 +
      91 +	if (!(flag & AT_REMOVEDIR)) {
      92 +		/* Behave like unlink() */
      93 +		if ((fstatat64(atfd, pathname, &statbuf, AT_SYMLINK_NOFOLLOW) ==
      94 +		    0) && S_ISDIR(statbuf.st_mode))
      95 +			return (-EISDIR);
      96 +	}
      97 +
      98 +	return (unlinkat(atfd, pathname, flag) ? -errno : 0);
      99  }
     100  
     101  /*
     102 @@ -466,3 +529,213 @@
     103  
     104  	return (-EINVAL);
     105  }
     106 +
     107 +int
     108 +lx_faccessat(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4)
     109 +{
     110 +	int atfd = (int)p1;
     111 +	char *path = (char *)p2;
     112 +	int mode = (mode_t)p3;
     113 +	int flag = (int)p4;
     114 +
     115 +	if (atfd == LX_AT_FDCWD)
     116 +		atfd = AT_FDCWD;
     117 +
     118 +	flag = ltos_at_flag(flag, AT_EACCESS);
     119 +	if (flag < 0)
     120 +		return (-EINVAL);
     121 +
     122 +	return (faccessat(atfd, path, mode, flag) ? -errno : 0);
     123 +}
     124 +
     125 +int
     126 +lx_futimesat(uintptr_t p1, uintptr_t p2, uintptr_t p3)
     127 +{
     128 +	int atfd = (int)p1;
     129 +	char *path = (char *)p2;
     130 +	struct timeval *times = (struct timeval *)p3;
     131 +
     132 +	if (atfd == LX_AT_FDCWD)
     133 +		atfd = AT_FDCWD;
     134 +
     135 +	return (futimesat(atfd, path, times) ? -errno : 0);
     136 +}
     137 +
     138 +
     139 +/*
     140 + * Constructs an absolute path string in buf from the path of fd and the
     141 + * relative path string pointed to by "p1". This is required for emulating
     142 + * *at() system calls.
     143 + * Example:
     144 + *    If the path of fd is "/foo/bar" and path is "etc" the string returned is
     145 + *    "/foo/bar/etc", if the fd is a file fd then it fails with ENOTDIR.
     146 + *    If path is absolute then no modifcations are made to it when copied.
     147 + */
     148 +static int
     149 +getpathat(int fd, uintptr_t p1, char *outbuf, size_t outbuf_size)
     150 +{
     151 +	char pathbuf[MAXPATHLEN];
     152 +	char fdpathbuf[MAXPATHLEN];
     153 +	char *fdpath;
     154 +	struct stat64 statbuf;
     155 +
     156 +	if (uucopystr((void *)p1, pathbuf, MAXPATHLEN) == -1)
     157 +		return (-errno);
     158 +
     159 +	/* If the path is absolute then we can early out */
     160 +	if ((pathbuf[0] == '/') || (fd == LX_AT_FDCWD)) {
     161 +		(void) strlcpy(outbuf, pathbuf, outbuf_size);
     162 +		return (0);
     163 +	}
     164 +
     165 +	fdpath = lx_fd_to_path(fd, fdpathbuf, sizeof (fdpathbuf));
     166 +	if (fdpath == NULL)
     167 +		return (-EBADF);
     168 +
     169 +	if ((fstat64(fd, &statbuf) < 0))
     170 +		return (-EBADF);
     171 +
     172 +	if (!S_ISDIR(statbuf.st_mode))
     173 +		return (-ENOTDIR);
     174 +
     175 +	if (snprintf(outbuf, outbuf_size, "%s/%s", fdpath, pathbuf) >
     176 +	    (outbuf_size-1))
     177 +		return (-ENAMETOOLONG);
     178 +
     179 +	return (0);
     180 +}
     181 +
     182 +int
     183 +lx_mkdirat(uintptr_t p1, uintptr_t p2, uintptr_t p3)
     184 +{
     185 +	int atfd = (int)p1;
     186 +	mode_t mode = (mode_t)p3;
     187 +	char pathbuf[MAXPATHLEN];
     188 +	int ret;
     189 +
     190 +	ret = getpathat(atfd, p2, pathbuf, sizeof (pathbuf));
     191 +	if (ret < 0)
     192 +		return (ret);
     193 +
     194 +	return (mkdir(pathbuf, mode) ? -errno : 0);
     195 +}
     196 +
     197 +int
     198 +lx_mknodat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)
     199 +{
     200 +	int atfd = (int)ext1;
     201 +	char pathbuf[MAXPATHLEN];
     202 +	int ret;
     203 +
     204 +	ret = getpathat(atfd, p1, pathbuf, sizeof (pathbuf));
     205 +	if (ret < 0)
     206 +		return (ret);
     207 +
     208 +	return (lx_mknod((uintptr_t)pathbuf, p2, p3));
     209 +}
     210 +
     211 +int
     212 +lx_symlinkat(uintptr_t p1, uintptr_t ext1, uintptr_t p2)
     213 +{
     214 +	int atfd = (int)ext1;
     215 +	char pathbuf[MAXPATHLEN];
     216 +	int ret;
     217 +
     218 +	ret = getpathat(atfd, p2, pathbuf, sizeof (pathbuf));
     219 +	if (ret < 0)
     220 +		return (ret);
     221 +
     222 +	return (symlink((char *)p1, pathbuf) ? -errno : 0);
     223 +}
     224 +
     225 +int
     226 +lx_linkat(uintptr_t ext1, uintptr_t p1, uintptr_t ext2, uintptr_t p2,
     227 +    uintptr_t p3)
     228 +{
     229 +	int atfd1 = (int)ext1;
     230 +	int atfd2 = (int)ext2;
     231 +	char pathbuf1[MAXPATHLEN];
     232 +	char pathbuf2[MAXPATHLEN];
     233 +	int ret;
     234 +
     235 +	/*
     236 +	 * The flag specifies whether the hardlink will point to a symlink or
     237 +	 * not, on solaris the default behaviour of link() is to dereference a
     238 +	 * symlink and there is no obvious way to trigger the other behaviour.
     239 +	 * So for now we just ignore this flag and act like link().
     240 +	 */
     241 +	/* LINTED [set but not used in function] */
     242 +	int flag = p3;
     243 +
     244 +	ret = getpathat(atfd1, p1, pathbuf1, sizeof (pathbuf1));
     245 +	if (ret < 0)
     246 +		return (ret);
     247 +
     248 +	ret = getpathat(atfd2, p2, pathbuf2, sizeof (pathbuf2));
     249 +	if (ret < 0)
     250 +		return (ret);
     251 +
     252 +	return (lx_link((uintptr_t)pathbuf1, (uintptr_t)pathbuf2));
     253 +}
     254 +
     255 +int
     256 +lx_readlinkat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)
     257 +{
     258 +	int atfd = (int)ext1;
     259 +	char pathbuf[MAXPATHLEN];
     260 +	int ret;
     261 +
     262 +	ret = getpathat(atfd, p1, pathbuf, sizeof (pathbuf));
     263 +	if (ret < 0)
     264 +		return (ret);
     265 +
     266 +	ret = readlink(pathbuf, (char *)p2, (size_t)p3);
     267 +	if (ret < 0)
     268 +		return (-errno);
     269 +
     270 +	return (ret);
     271 +}
     272 +
     273 +int
     274 +lx_fchownat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3,
     275 +    uintptr_t p4)
     276 +{
     277 +	int flag;
     278 +	int atfd = (int)ext1;
     279 +	char pathbuf[MAXPATHLEN];
     280 +	int ret;
     281 +
     282 +	flag = ltos_at_flag(p4, AT_SYMLINK_NOFOLLOW);
     283 +	if (flag < 0)
     284 +		return (-EINVAL);
     285 +
     286 +	ret = getpathat(atfd, p1, pathbuf, sizeof (pathbuf));
     287 +	if (ret < 0)
     288 +		return (ret);
     289 +
     290 +	if (flag & AT_SYMLINK_NOFOLLOW)
     291 +		return (lchown(pathbuf, (uid_t)p2, (gid_t)p3) ? -errno : 0);
     292 +	else
     293 +		return (lx_chown((uintptr_t)pathbuf, p2, p3));
     294 +}
     295 +
     296 +int
     297 +lx_fchmodat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)
     298 +{
     299 +	int atfd = (int)ext1;
     300 +	char pathbuf[MAXPATHLEN];
     301 +	int ret;
     302 +
     303 +	/*
     304 +	 * It seems that at least some versions of glibc do not set or clear
     305 +	 * the flags arg, so checking them will result in random behaviour.
     306 +	 */
     307 +	/* LINTED [set but not used in function] */
     308 +	int flag = p3;
     309 +
     310 +	ret = getpathat(atfd, p1, pathbuf, sizeof (pathbuf));
     311 +	if (ret < 0)
     312 +		return (ret);
     313 +
     314 +	return (lx_chmod((uintptr_t)pathbuf, p2));
     315 +}
     1.1 --- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c	Wed Dec 16 16:39:00 2009 -0800
     1.2 +++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c	Wed Dec 16 18:25:17 2009 -0800
     1.3 @@ -20,11 +20,9 @@
     1.4   */
     1.5  
     1.6  /*
     1.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     1.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     1.9   * Use is subject to license terms.
    1.10   */
    1.11 -
    1.12 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    1.13  
    1.14  #include <sys/types.h>
    1.15  #include <sys/syscall.h>
    1.16 @@ -1274,19 +1272,19 @@
    1.17  	{"inotify_add_watch", NULL,	NOSYS_NULL,	0},	/* 292 */
    1.18  	{"inotify_rm_watch", NULL,	NOSYS_NULL,	0},	/* 293 */
    1.19  	{"migrate_pages", NULL,		NOSYS_NULL,	0},	/* 294 */
    1.20 -	{"openat",	NULL,		NOSYS_NULL,	0},	/* 295 */
    1.21 -	{"mkdirat",	NULL,		NOSYS_NULL,	0},	/* 296 */
    1.22 -	{"mknodat",	NULL,		NOSYS_NULL,	0},	/* 297 */
    1.23 -	{"fchownat",	NULL,		NOSYS_NULL,	0},	/* 298 */
    1.24 -	{"futimesat",	NULL,		NOSYS_NULL,	0},	/* 299 */
    1.25 -	{"fstatat64",	NULL,		NOSYS_NULL,	0},	/* 300 */
    1.26 -	{"unlinkat",	NULL,		NOSYS_NULL,	0},	/* 301 */
    1.27 -	{"renameat",	NULL,		NOSYS_NULL,	0},	/* 302 */
    1.28 -	{"linkat",	NULL,		NOSYS_NULL,	0},	/* 303 */
    1.29 -	{"symlinkat",	NULL,		NOSYS_NULL,	0},	/* 304 */
    1.30 -	{"readlinkat",	NULL,		NOSYS_NULL,	0},	/* 305 */
    1.31 -	{"fchmodat",	NULL,		NOSYS_NULL,	0},	/* 306 */
    1.32 -	{"faccessat",	NULL,		NOSYS_NULL,	0},	/* 307 */
    1.33 +	{"openat",	lx_openat,	0,		4},	/* 295 */
    1.34 +	{"mkdirat",	lx_mkdirat,	0,		3},	/* 296 */
    1.35 +	{"mknodat",	lx_mknodat,	0,		4},	/* 297 */
    1.36 +	{"fchownat",	lx_fchownat,	0,		5},	/* 298 */
    1.37 +	{"futimesat",	lx_futimesat,	0,		3},	/* 299 */
    1.38 +	{"fstatat64",	lx_fstatat64,	0,		4},	/* 300 */
    1.39 +	{"unlinkat",	lx_unlinkat,	0,		3},	/* 301 */
    1.40 +	{"renameat",	lx_renameat,	0,		4},	/* 302 */
    1.41 +	{"linkat",	lx_linkat,	0,		5},	/* 303 */
    1.42 +	{"symlinkat",	lx_symlinkat,	0,		3},	/* 304 */
    1.43 +	{"readlinkat",	lx_readlinkat,	0,		4},	/* 305 */
    1.44 +	{"fchmodat",	lx_fchmodat,	0,		4},	/* 306 */
    1.45 +	{"faccessat",	lx_faccessat,	0,		4},	/* 307 */
    1.46  	{"pselect6",	NULL,		NOSYS_NULL,	0},	/* 308 */
    1.47  	{"ppoll",	NULL,		NOSYS_NULL,	0},	/* 309 */
    1.48  	{"unshare",	NULL,		NOSYS_NULL,	0},	/* 310 */
     2.1 --- a/usr/src/lib/brand/lx/lx_brand/common/misc.c	Wed Dec 16 16:39:00 2009 -0800
     2.2 +++ b/usr/src/lib/brand/lx/lx_brand/common/misc.c	Wed Dec 16 18:25:17 2009 -0800
     2.3 @@ -19,11 +19,9 @@
     2.4   * CDDL HEADER END
     2.5   */
     2.6  /*
     2.7 - * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     2.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     2.9   * Use is subject to license terms.
    2.10   */
    2.11 -
    2.12 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    2.13  
    2.14  #include <assert.h>
    2.15  #include <alloca.h>
    2.16 @@ -44,6 +42,7 @@
    2.17  #include <sys/lx_stat.h>
    2.18  #include <sys/lx_syscall.h>
    2.19  #include <sys/lx_thunk_server.h>
    2.20 +#include <sys/lx_fcntl.h>
    2.21  #include <unistd.h>
    2.22  #include <libintl.h>
    2.23  #include <zone.h>
    2.24 @@ -76,6 +75,39 @@
    2.25  
    2.26  			if (errno == EBUSY) {
    2.27  				(void) unlink((const char *)p1);
    2.28 +				return (0);
    2.29 +			}
    2.30 +		}
    2.31 +
    2.32 +		return (-errno);
    2.33 +	}
    2.34 +
    2.35 +	return (0);
    2.36 +}
    2.37 +
    2.38 +int
    2.39 +lx_renameat(uintptr_t ext1, uintptr_t p1, uintptr_t ext2, uintptr_t p2)
    2.40 +{
    2.41 +	int ret;
    2.42 +	int atfd1 = (int)ext1;
    2.43 +	int atfd2 = (int)ext2;
    2.44 +
    2.45 +	if (atfd1 == LX_AT_FDCWD)
    2.46 +		atfd1 = AT_FDCWD;
    2.47 +
    2.48 +	if (atfd2 == LX_AT_FDCWD)
    2.49 +		atfd2 = AT_FDCWD;
    2.50 +
    2.51 +	ret = renameat(atfd1, (const char *)p1, atfd2, (const char *)p2);
    2.52 +
    2.53 +	if (ret < 0) {
    2.54 +		/* see lx_rename() for why we check lx_install */
    2.55 +		if (lx_install != 0) {
    2.56 +			if (errno == ENOENT)
    2.57 +				return (0);
    2.58 +
    2.59 +			if (errno == EBUSY) {
    2.60 +				(void) unlinkat(ext1, (const char *)p1, 0);
    2.61  				return (0);
    2.62  			}
    2.63  		}
     3.1 --- a/usr/src/lib/brand/lx/lx_brand/common/open.c	Wed Dec 16 16:39:00 2009 -0800
     3.2 +++ b/usr/src/lib/brand/lx/lx_brand/common/open.c	Wed Dec 16 18:25:17 2009 -0800
     3.3 @@ -20,11 +20,9 @@
     3.4   */
     3.5  
     3.6  /*
     3.7 - * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     3.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     3.9   * Use is subject to license terms.
    3.10   */
    3.11 -
    3.12 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    3.13  
    3.14  #include <sys/types.h>
    3.15  #include <sys/stat.h>
    3.16 @@ -41,13 +39,10 @@
    3.17  #include <sys/lx_fcntl.h>
    3.18  #include <sys/lx_misc.h>
    3.19  
    3.20 -int
    3.21 -lx_open(uintptr_t p1, uintptr_t p2, uintptr_t p3)
    3.22 +static int
    3.23 +ltos_open_flags(uintptr_t p2)
    3.24  {
    3.25 -	int flags, fd;
    3.26 -	mode_t mode = 0;
    3.27 -	char *path = (char *)p1;
    3.28 -	struct stat64 statbuf;
    3.29 +	int flags;
    3.30  
    3.31  	if ((p2 & O_ACCMODE) == LX_O_RDONLY)
    3.32  		flags = O_RDONLY;
    3.33 @@ -58,7 +53,6 @@
    3.34  
    3.35  	if (p2 & LX_O_CREAT) {
    3.36  		flags |= O_CREAT;
    3.37 -		mode = (mode_t)p3;
    3.38  	}
    3.39  
    3.40  	if (p2 & LX_O_EXCL)
    3.41 @@ -99,10 +93,13 @@
    3.42  	if (p2 & LX_O_DIRECT)
    3.43  		flags |= (O_RSYNC|O_SYNC);
    3.44  
    3.45 -	lx_debug("\topen(%s, 0%o, 0%o)", path, flags, mode);
    3.46 +	return (flags);
    3.47 +}
    3.48  
    3.49 -	if ((fd = open(path, flags, mode)) < 0)
    3.50 -		return (-errno);
    3.51 +static int
    3.52 +lx_open_postprocess(int fd, uintptr_t p2)
    3.53 +{
    3.54 +	struct stat64 statbuf;
    3.55  
    3.56  	/*
    3.57  	 * Check the file type AFTER opening the file to avoid a race condition
    3.58 @@ -138,3 +135,49 @@
    3.59  
    3.60  	return (fd);
    3.61  }
    3.62 +
    3.63 +int
    3.64 +lx_openat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)
    3.65 +{
    3.66 +	int atfd = (int)ext1;
    3.67 +	int flags, fd;
    3.68 +	mode_t mode = 0;
    3.69 +	char *path = (char *)p1;
    3.70 +
    3.71 +	if (atfd == LX_AT_FDCWD)
    3.72 +		atfd = AT_FDCWD;
    3.73 +
    3.74 +	flags = ltos_open_flags(p2);
    3.75 +
    3.76 +	if (flags & O_CREAT) {
    3.77 +		mode = (mode_t)p3;
    3.78 +	}
    3.79 +
    3.80 +	lx_debug("\topenat(%d, %s, 0%o, 0%o)", atfd, path, flags, mode);
    3.81 +
    3.82 +	if ((fd = openat(atfd, path, flags, mode)) < 0)
    3.83 +		return (-errno);
    3.84 +
    3.85 +	return (lx_open_postprocess(fd, p2));
    3.86 +}
    3.87 +
    3.88 +int
    3.89 +lx_open(uintptr_t p1, uintptr_t p2, uintptr_t p3)
    3.90 +{
    3.91 +	int flags, fd;
    3.92 +	mode_t mode = 0;
    3.93 +	char *path = (char *)p1;
    3.94 +
    3.95 +	flags = ltos_open_flags(p2);
    3.96 +
    3.97 +	if (flags & O_CREAT) {
    3.98 +		mode = (mode_t)p3;
    3.99 +	}
   3.100 +
   3.101 +	lx_debug("\topen(%s, 0%o, 0%o)", path, flags, mode);
   3.102 +
   3.103 +	if ((fd = open(path, flags, mode)) < 0)
   3.104 +		return (-errno);
   3.105 +
   3.106 +	return (lx_open_postprocess(fd, p2));
   3.107 +}
     4.1 --- a/usr/src/lib/brand/lx/lx_brand/common/stat.c	Wed Dec 16 16:39:00 2009 -0800
     4.2 +++ b/usr/src/lib/brand/lx/lx_brand/common/stat.c	Wed Dec 16 18:25:17 2009 -0800
     4.3 @@ -19,11 +19,9 @@
     4.4   * CDDL HEADER END
     4.5   */
     4.6  /*
     4.7 - * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     4.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     4.9   * Use is subject to license terms.
    4.10   */
    4.11 -
    4.12 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    4.13  
    4.14  /*
    4.15   * when a stat() is done for a non-device file, the devt returned
    4.16 @@ -55,6 +53,7 @@
    4.17  #include <sys/lx_debug.h>
    4.18  #include <sys/lx_ptm.h>
    4.19  #include <sys/lx_audio.h>
    4.20 +#include <sys/lx_fcntl.h>
    4.21  #include <sys/modctl.h>
    4.22  
    4.23  /* define _KERNEL to get the devt manipulation macros */
    4.24 @@ -472,6 +471,27 @@
    4.25  	return (stat64_convert(p2, &sbuf, fd));
    4.26  }
    4.27  
    4.28 +int
    4.29 +lx_fstatat64(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4)
    4.30 +{
    4.31 +	int atfd = (int)p1;
    4.32 +	const char *path = (const char *)p2;
    4.33 +	int flag;
    4.34 +	struct stat64 sbuf;
    4.35 +
    4.36 +	if (atfd == LX_AT_FDCWD)
    4.37 +		atfd = AT_FDCWD;
    4.38 +
    4.39 +	flag = ltos_at_flag(p4, AT_SYMLINK_NOFOLLOW);
    4.40 +	if (flag < 0)
    4.41 +		return (-EINVAL);
    4.42 +
    4.43 +	if (fstatat64(atfd, path, &sbuf, flag))
    4.44 +		return (-errno);
    4.45 +
    4.46 +	return (stat64_convert(p3, &sbuf, -1));
    4.47 +}
    4.48 +
    4.49  
    4.50  int
    4.51  lx_lstat64(uintptr_t p1, uintptr_t p2)
     5.1 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_fcntl.h	Wed Dec 16 16:39:00 2009 -0800
     5.2 +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_fcntl.h	Wed Dec 16 18:25:17 2009 -0800
     5.3 @@ -19,14 +19,12 @@
     5.4   * CDDL HEADER END
     5.5   */
     5.6  /*
     5.7 - * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     5.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     5.9   * Use is subject to license terms.
    5.10   */
    5.11  
    5.12  #ifndef _SYS_LX_FCNTL_H
    5.13  #define	_SYS_LX_FCNTL_H
    5.14 -
    5.15 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    5.16  
    5.17  #ifdef	__cplusplus
    5.18  extern "C" {
    5.19 @@ -87,6 +85,12 @@
    5.20  #define	LX_LOCK_NB		4	/* non-blocking */
    5.21  #define	LX_LOCK_UN		8	/* unlock */
    5.22  
    5.23 +#define	LX_AT_FDCWD		-100
    5.24 +#define	LX_AT_EACCESS		512
    5.25 +#define	LX_AT_REMOVEDIR		512
    5.26 +#define	LX_AT_SYMLINK_NOFOLLOW	256
    5.27 +#define	LX_AT_SYMLINK_FOLLOW	1024
    5.28 +
    5.29  struct lx_flock {
    5.30  	short		l_type;
    5.31  	short		l_whence;
     6.1 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h	Wed Dec 16 16:39:00 2009 -0800
     6.2 +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h	Wed Dec 16 18:25:17 2009 -0800
     6.3 @@ -20,14 +20,12 @@
     6.4   */
     6.5  
     6.6  /*
     6.7 - * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     6.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     6.9   * Use is subject to license terms.
    6.10   */
    6.11  
    6.12  #ifndef _SYS_LX_H
    6.13  #define	_SYS_LX_H
    6.14 -
    6.15 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    6.16  
    6.17  #include <stdio.h>
    6.18  #include <alloca.h>
    6.19 @@ -132,6 +130,8 @@
    6.20  extern int lx_check_alloca(size_t);
    6.21  #define	SAFE_ALLOCA(sz)	(lx_check_alloca(sz) ? alloca(sz) : NULL)
    6.22  
    6.23 +extern int ltos_at_flag(int lflag, int allow);
    6.24 +
    6.25  /*
    6.26   * NO_UUCOPY disables calls to the uucopy* system calls to help with
    6.27   * debugging brand library accesses to linux application memory.
     7.1 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h	Wed Dec 16 16:39:00 2009 -0800
     7.2 +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h	Wed Dec 16 18:25:17 2009 -0800
     7.3 @@ -20,14 +20,12 @@
     7.4   */
     7.5  
     7.6  /*
     7.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     7.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     7.9   * Use is subject to license terms.
    7.10   */
    7.11  
    7.12  #ifndef _SYS_LX_SYSCALL_H
    7.13  #define	_SYS_LX_SYSCALL_H
    7.14 -
    7.15 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
    7.16  
    7.17  #if !defined(_ASM)
    7.18  
    7.19 @@ -39,6 +37,20 @@
    7.20  #endif
    7.21  
    7.22  extern int lx_install;
    7.23 +
    7.24 +extern int lx_openat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.25 +extern int lx_mkdirat(uintptr_t, uintptr_t, uintptr_t);
    7.26 +extern int lx_mknodat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.27 +extern int lx_fchownat(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.28 +extern int lx_futimesat(uintptr_t, uintptr_t, uintptr_t);
    7.29 +extern int lx_fstatat64(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.30 +extern int lx_unlinkat(uintptr_t, uintptr_t, uintptr_t);
    7.31 +extern int lx_renameat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.32 +extern int lx_linkat(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.33 +extern int lx_symlinkat(uintptr_t, uintptr_t, uintptr_t);
    7.34 +extern int lx_readlinkat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.35 +extern int lx_fchmodat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.36 +extern int lx_faccessat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
    7.37  
    7.38  extern int lx_stat(uintptr_t, uintptr_t);
    7.39  extern int lx_fstat(uintptr_t, uintptr_t);