summaryrefslogtreecommitdiff
path: root/mysys/my_symlink.c
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-02-20 22:41:17 +0100
committerSergei Golubchik <serg@mariadb.org>2017-02-27 12:35:10 +0100
commit6d50324558e79d6e90848059bf7cd918685b02ba (patch)
treec120ea5c18468c2947b0af18a4c79980e3f57f6f /mysys/my_symlink.c
parentf2d24ea68b9fde45d9a221f2c2a5d75fd10ef650 (diff)
downloadmariadb-git-6d50324558e79d6e90848059bf7cd918685b02ba.tar.gz
support MY_NOSYMLINKS in my_delete()
Diffstat (limited to 'mysys/my_symlink.c')
-rw-r--r--mysys/my_symlink.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index bc01a68263d..ed35fff41e9 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -177,3 +177,78 @@ int my_realpath(char *to, const char *filename, myf MyFlags)
#endif
return 0;
}
+
+#ifdef HAVE_OPEN_PARENT_DIR_NOSYMLINKS
+/** opens the parent dir. walks the path, and does not resolve symlinks
+
+ returns the pointer to the file name (basename) within the pathname
+ or NULL in case of an error
+
+ stores the parent dir (dirname) file descriptor in pdfd.
+ It can be -1 even if there was no error!
+
+ This is used for symlinked tables for DATA/INDEX DIRECTORY.
+ The paths there have been realpath()-ed. So, we can assume here that
+
+ * `pathname` is an absolute path
+ * no '.', '..', and '//' in the path
+ * file exists
+*/
+
+const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd)
+{
+ char buf[PATH_MAX+1];
+ char *s= buf, *e= buf+1, *end= strnmov(buf, pathname, sizeof(buf));
+ int fd, dfd= -1;
+
+ if (*end)
+ {
+ errno= ENAMETOOLONG;
+ return NULL;
+ }
+
+ if (*s != '/') /* not an absolute path */
+ {
+ errno= ENOENT;
+ return NULL;
+ }
+
+ for (;;)
+ {
+ if (*e == '/') /* '//' in the path */
+ {
+ errno= ENOENT;
+ goto err;
+ }
+ while (*e && *e != '/')
+ e++;
+ *e= 0;
+
+ if (!memcmp(s, ".", 2) || !memcmp(s, "..", 3))
+ {
+ errno= ENOENT;
+ goto err;
+ }
+
+ if (++e >= end)
+ {
+ *pdfd= dfd;
+ return pathname + (s - buf);
+ }
+
+ fd = openat(dfd, s, O_NOFOLLOW | O_PATH);
+ if (fd < 0)
+ goto err;
+
+ if (dfd >= 0)
+ close(dfd);
+
+ dfd= fd;
+ s= e;
+ }
+err:
+ if (dfd >= 0)
+ close(dfd);
+ return NULL;
+}
+#endif