Skip to content

Commit 6d50324

Browse files
committed
support MY_NOSYMLINKS in my_delete()
1 parent f2d24ea commit 6d50324

File tree

4 files changed

+118
-84
lines changed

4 files changed

+118
-84
lines changed

mysys/my_delete.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
static int my_win_unlink(const char *name);
2222
#endif
2323

24+
CREATE_NOSYMLINK_FUNCTION(
25+
unlink_nosymlinks(const char *pathname),
26+
unlinkat(dfd, filename, 0),
27+
unlink(pathname)
28+
);
29+
2430
int my_delete(const char *name, myf MyFlags)
2531
{
2632
int err;
@@ -30,7 +36,10 @@ int my_delete(const char *name, myf MyFlags)
3036
#ifdef _WIN32
3137
err = my_win_unlink(name);
3238
#else
33-
err = unlink(name);
39+
if (MyFlags & MY_NOSYMLINKS)
40+
err= unlink_nosymlinks(name);
41+
else
42+
err= unlink(name);
3443
#endif
3544

3645
if(err)

mysys/my_open.c

Lines changed: 5 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
#include <m_string.h>
1919
#include <errno.h>
2020

21-
#if !defined(O_PATH) && defined(O_EXEC) /* FreeBSD */
22-
#define O_PATH O_EXEC
23-
#endif
24-
25-
static int open_nosymlinks(const char *pathname, int flags, int mode);
21+
CREATE_NOSYMLINK_FUNCTION(
22+
open_nosymlinks(const char *pathname, int flags, int mode),
23+
openat(dfd, filename, O_NOFOLLOW | flags, mode),
24+
open(pathname, O_NOFOLLOW | flags, mode)
25+
);
2626

2727
/*
2828
Open a file
@@ -182,81 +182,3 @@ void my_print_open_files(void)
182182
}
183183

184184
#endif
185-
186-
/**
187-
like open(), but with symlinks are not accepted anywhere in the path
188-
189-
This is used for opening symlinked tables for DATA/INDEX DIRECTORY.
190-
The paths there have been realpath()-ed. So, we can assume here that
191-
192-
* `pathname` is an absolute path
193-
* no '.', '..', and '//' in the path
194-
* file exists
195-
*/
196-
static int open_nosymlinks(const char *pathname, int flags, int mode)
197-
{
198-
#ifndef O_PATH
199-
#ifdef HAVE_REALPATH
200-
char buf[PATH_MAX+1];
201-
if (realpath(pathname, buf) == NULL)
202-
return -1;
203-
if (strcmp(pathname, buf))
204-
{
205-
errno= ENOTDIR;
206-
return -1;
207-
}
208-
#endif
209-
return open(pathname, flags, mode | O_NOFOLLOW);
210-
#else
211-
212-
char buf[PATH_MAX+1];
213-
char *s= buf, *e= buf+1, *end= strnmov(buf, pathname, sizeof(buf));
214-
int fd, dfd= -1;
215-
216-
if (*end)
217-
{
218-
errno= ENAMETOOLONG;
219-
return -1;
220-
}
221-
222-
if (*s != '/') /* not an absolute path */
223-
{
224-
errno= ENOENT;
225-
return -1;
226-
}
227-
228-
for (;;)
229-
{
230-
if (*e == '/') /* '//' in the path */
231-
{
232-
errno= ENOENT;
233-
goto err;
234-
}
235-
while (*e && *e != '/')
236-
e++;
237-
*e= 0;
238-
if (!memcmp(s, ".", 2) || !memcmp(s, "..", 3))
239-
{
240-
errno= ENOENT;
241-
goto err;
242-
}
243-
244-
fd = openat(dfd, s, O_NOFOLLOW | (e < end ? O_PATH : flags), mode);
245-
if (fd < 0)
246-
goto err;
247-
248-
if (dfd >= 0)
249-
close(dfd);
250-
251-
dfd= fd;
252-
s= ++e;
253-
254-
if (e >= end)
255-
return fd;
256-
}
257-
err:
258-
if (dfd >= 0)
259-
close(dfd);
260-
return -1;
261-
#endif
262-
}

mysys/my_symlink.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,78 @@ int my_realpath(char *to, const char *filename, myf MyFlags)
177177
#endif
178178
return 0;
179179
}
180+
181+
#ifdef HAVE_OPEN_PARENT_DIR_NOSYMLINKS
182+
/** opens the parent dir. walks the path, and does not resolve symlinks
183+
184+
returns the pointer to the file name (basename) within the pathname
185+
or NULL in case of an error
186+
187+
stores the parent dir (dirname) file descriptor in pdfd.
188+
It can be -1 even if there was no error!
189+
190+
This is used for symlinked tables for DATA/INDEX DIRECTORY.
191+
The paths there have been realpath()-ed. So, we can assume here that
192+
193+
* `pathname` is an absolute path
194+
* no '.', '..', and '//' in the path
195+
* file exists
196+
*/
197+
198+
const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd)
199+
{
200+
char buf[PATH_MAX+1];
201+
char *s= buf, *e= buf+1, *end= strnmov(buf, pathname, sizeof(buf));
202+
int fd, dfd= -1;
203+
204+
if (*end)
205+
{
206+
errno= ENAMETOOLONG;
207+
return NULL;
208+
}
209+
210+
if (*s != '/') /* not an absolute path */
211+
{
212+
errno= ENOENT;
213+
return NULL;
214+
}
215+
216+
for (;;)
217+
{
218+
if (*e == '/') /* '//' in the path */
219+
{
220+
errno= ENOENT;
221+
goto err;
222+
}
223+
while (*e && *e != '/')
224+
e++;
225+
*e= 0;
226+
227+
if (!memcmp(s, ".", 2) || !memcmp(s, "..", 3))
228+
{
229+
errno= ENOENT;
230+
goto err;
231+
}
232+
233+
if (++e >= end)
234+
{
235+
*pdfd= dfd;
236+
return pathname + (s - buf);
237+
}
238+
239+
fd = openat(dfd, s, O_NOFOLLOW | O_PATH);
240+
if (fd < 0)
241+
goto err;
242+
243+
if (dfd >= 0)
244+
close(dfd);
245+
246+
dfd= fd;
247+
s= e;
248+
}
249+
err:
250+
if (dfd >= 0)
251+
close(dfd);
252+
return NULL;
253+
}
254+
#endif

mysys/mysys_priv.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,34 @@ void sf_free(void *ptr);
8989

9090
void my_error_unregister_all(void);
9191

92+
#if !defined(O_PATH) && defined(O_EXEC) /* FreeBSD */
93+
#define O_PATH O_EXEC
94+
#endif
95+
96+
#ifdef O_PATH
97+
#define HAVE_OPEN_PARENT_DIR_NOSYMLINKS
98+
const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd);
99+
#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \
100+
int dfd, res; \
101+
const char *filename= my_open_parent_dir_nosymlinks(pathname, &dfd); \
102+
if (filename == NULL) return -1; \
103+
res= AT; \
104+
if (dfd >= 0) close(dfd); \
105+
return res;
106+
#elif defined(HAVE_REALPATH)
107+
#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \
108+
char buf[PATH_MAX+1]; \
109+
if (realpath(pathname, buf) == NULL) return -1; \
110+
if (strcmp(pathname, buf)) { errno= ENOTDIR; return -1; } \
111+
return NOAT;
112+
#else
113+
#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \
114+
return NOAT;
115+
#endif
116+
117+
#define CREATE_NOSYMLINK_FUNCTION(PROTO,AT,NOAT) \
118+
static int PROTO { NOSYMLINK_FUNCTION_BODY(AT,NOAT) }
119+
92120
#ifdef _WIN32
93121
#include <sys/stat.h>
94122
/* my_winfile.c exports, should not be used outside mysys */

0 commit comments

Comments
 (0)