mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
scanner: Ensure parent directory exists for output file
Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
parent
264da6a92b
commit
3cbf08f29e
1 changed files with 94 additions and 2 deletions
|
|
@ -37,6 +37,8 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#if HAVE_LIBXML
|
#if HAVE_LIBXML
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
|
|
@ -2031,6 +2033,87 @@ free_protocol(struct protocol *protocol)
|
||||||
free_description(protocol->description);
|
free_description(protocol->description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ensure_parent_dir(const char *path, mode_t mode) {
|
||||||
|
if (path == NULL || *path == '\0') {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path_copy[PATH_MAX];
|
||||||
|
size_t len = strlen(path);
|
||||||
|
if (len >= sizeof(path_copy)) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(path_copy, path, len + 1);
|
||||||
|
|
||||||
|
/* Remove trailing slashes unless it's the root */
|
||||||
|
while (len > 1 && path_copy[len - 1] == '/')
|
||||||
|
path_copy[--len] = '\0';
|
||||||
|
|
||||||
|
char *last_slash = strrchr(path_copy, '/');
|
||||||
|
if (last_slash == NULL || last_slash == path_copy)
|
||||||
|
return 0;
|
||||||
|
*last_slash = '\0';
|
||||||
|
|
||||||
|
/* start walking directories */
|
||||||
|
int dfd = AT_FDCWD;
|
||||||
|
int ret = 0;
|
||||||
|
char *p = path_copy;
|
||||||
|
|
||||||
|
if (*p == '/') {
|
||||||
|
dfd = open("/", O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dfd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (*p == '/')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p != '\0') {
|
||||||
|
char *slash = strchr(p, '/');
|
||||||
|
if (slash != NULL)
|
||||||
|
*slash = '\0';
|
||||||
|
|
||||||
|
int new_dfd = openat(dfd, p, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (new_dfd < 0) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
if (mkdirat(dfd, p, mode) < 0 && errno != EEXIST) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_dfd = openat(dfd, p, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (new_dfd < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dfd != AT_FDCWD)
|
||||||
|
close(dfd);
|
||||||
|
dfd = new_dfd;
|
||||||
|
|
||||||
|
if (slash == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*slash = '/';
|
||||||
|
p = slash + 1;
|
||||||
|
while (*p == '/')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (dfd != AT_FDCWD)
|
||||||
|
close(dfd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct parse_context ctx;
|
struct parse_context ctx;
|
||||||
|
|
@ -2120,8 +2203,17 @@ int main(int argc, char *argv[])
|
||||||
fprintf(stderr, "Could not open input file: %s\n",
|
fprintf(stderr, "Could not open input file: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (freopen(argv[2], "w", stdout) == NULL) {
|
|
||||||
|
/* ensure the parent directory of the output file exists */
|
||||||
|
if (ensure_parent_dir(argv[2], 0755) < 0) {
|
||||||
|
fprintf(stderr, "Could not create parent directory of output file: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
fclose(input);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freopen(argv[2], "w", stdout) == NULL) {
|
||||||
fprintf(stderr, "Could not open output file: %s\n",
|
fprintf(stderr, "Could not open output file: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
fclose(input);
|
fclose(input);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue