scanner: Ensure parent directory exists for output file

Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
ComixHe 2025-09-11 13:26:22 +08:00
parent 264da6a92b
commit 3cbf08f29e
No known key found for this signature in database
GPG key ID: A184612DF59E3C3D

View file

@ -37,6 +37,8 @@
#include <getopt.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#if HAVE_LIBXML
#include <libxml/parser.h>
@ -2031,6 +2033,87 @@ free_protocol(struct protocol *protocol)
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[])
{
struct parse_context ctx;
@ -2120,8 +2203,17 @@ int main(int argc, char *argv[])
fprintf(stderr, "Could not open input file: %s\n",
strerror(errno));
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",
strerror(errno));
fclose(input);