[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/libc/glibc/glibc-2.22/elf/chroot_canon.c b/ap/libc/glibc/glibc-2.22/elf/chroot_canon.c
new file mode 100644
index 0000000..05a8241
--- /dev/null
+++ b/ap/libc/glibc/glibc-2.22/elf/chroot_canon.c
@@ -0,0 +1,177 @@
+/* Return the canonical absolute name of a given file inside chroot.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <eloop-threshold.h>
+#include <ldconfig.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/* Return the canonical absolute name of file NAME as if chroot(CHROOT) was
+ done first. A canonical name does not contain any `.', `..' components
+ nor any repeated path separators ('/') or symlinks. All path components
+ must exist and NAME must be absolute filename. The result is malloc'd.
+ The returned name includes the CHROOT prefix. */
+
+char *
+chroot_canon (const char *chroot, const char *name)
+{
+ char *rpath;
+ char *dest;
+ char *extra_buf = NULL;
+ char *rpath_root;
+ const char *start;
+ const char *end;
+ const char *rpath_limit;
+ int num_links = 0;
+ size_t chroot_len = strlen (chroot);
+
+ if (chroot_len < 1)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ rpath = xmalloc (chroot_len + PATH_MAX);
+
+ rpath_limit = rpath + chroot_len + PATH_MAX;
+
+ rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1;
+ if (*rpath_root != '/')
+ *++rpath_root = '/';
+ dest = rpath_root + 1;
+
+ for (start = end = name; *start; start = end)
+ {
+ struct stat64 st;
+
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath_root + 1)
+ while ((--dest)[-1] != '/');
+ }
+ else
+ {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit)
+ {
+ ptrdiff_t dest_offset = dest - rpath;
+ char *new_rpath;
+
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > PATH_MAX)
+ new_size += end - start + 1;
+ else
+ new_size += PATH_MAX;
+ new_rpath = (char *) xrealloc (rpath, new_size);
+ rpath = new_rpath;
+ rpath_limit = rpath + new_size;
+
+ dest = rpath + dest_offset;
+ }
+
+ dest = mempcpy (dest, start, end - start);
+ *dest = '\0';
+
+ if (lstat64 (rpath, &st) < 0)
+ {
+ if (*end == '\0')
+ goto done;
+ goto error;
+ }
+
+ if (S_ISLNK (st.st_mode))
+ {
+ char *buf = alloca (PATH_MAX);
+ size_t len;
+
+ if (++num_links > __eloop_threshold ())
+ {
+ __set_errno (ELOOP);
+ goto error;
+ }
+
+ ssize_t n = readlink (rpath, buf, PATH_MAX - 1);
+ if (n < 0)
+ {
+ if (*end == '\0')
+ goto done;
+ goto error;
+ }
+ buf[n] = '\0';
+
+ if (!extra_buf)
+ extra_buf = alloca (PATH_MAX);
+
+ len = strlen (end);
+ if (len >= PATH_MAX - n)
+ {
+ __set_errno (ENAMETOOLONG);
+ goto error;
+ }
+
+ /* Careful here, end may be a pointer into extra_buf... */
+ memmove (&extra_buf[n], end, len + 1);
+ name = end = memcpy (extra_buf, buf, n);
+
+ if (buf[0] == '/')
+ dest = rpath_root + 1; /* It's an absolute symlink */
+ else
+ /* Back up to previous component, ignore if at root already: */
+ if (dest > rpath_root + 1)
+ while ((--dest)[-1] != '/');
+ }
+ }
+ }
+ done:
+ if (dest > rpath_root + 1 && dest[-1] == '/')
+ --dest;
+ *dest = '\0';
+
+ return rpath;
+
+ error:
+ free (rpath);
+ return NULL;
+}