[LinuxBIOS] PATCH: mkdirp() error on new directory outside given parent
Peter Stuge
peter at stuge.se
Thu Jul 12 09:50:11 CEST 2007
Have a look.
I haven't gotten lar to build, but the function works in a separate
test program.
//Peter
-------------- next part --------------
Make mkdirp() abort directory creation and return an error if a directory
in dirpath is located outside the specified parent directory. Use the parent
"/" to allow new directories anywhere.
Signed-off-by: Peter Stuge <peter at stuge.se>
Index: util/lar/lib.c
===================================================================
--- util/lar/lib.c (revision 447)
+++ util/lar/lib.c (working copy)
@@ -24,6 +24,7 @@
#include <strings.h>
#include <unistd.h>
#include <dirent.h>
+#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -33,42 +34,72 @@
static struct file *files = NULL;
-int mkdirp(const char *dirpath, mode_t mode)
+/**
+ * Create a new directory including any missing parent directories.
+ *
+ * @param parent Return an error if a new directory would be created outside
+ * this directory. Pass "/" to allow new directories to be created anywhere.
+ * @param dirpath The new directory that should be created.
+ * @param mode Permissions to use for newly created directories.
+ */
+int mkdirp(const char *parent, const char *dirpath, mode_t mode)
{
- char *pos, *currpath, *path;
- char cwd[MAX_PATH];
- int ret = 0;
+ int ret = -1;
+ size_t dirsep, parlen, sublen;
+ char c, *r, *path = NULL, *subdir, rpar[PATH_MAX], rsub[PATH_MAX];
+ if (!dirpath) {
+ fprintf(stderr, "mkdirp: No new directory specified\n");
+ goto done;
+ }
+
path = strdup(dirpath);
if (!path) {
- fprintf(stderr, "Out of memory.\n");
- exit(1);
+ perror("Duplicate new directory failed:");
+ goto done;
}
- currpath = path;
-
- if (!getcwd(cwd, MAX_PATH)) {
- free(path);
- fprintf(stderr, "Error getting cwd.\n");
- return -1;
+ if (NULL == realpath(parent, rpar)) {
+ fprintf(stderr, "realpath(%s) failed: %s\n", parent,
+ strerror(errno));
+ goto done;
}
+ parlen = strlen(rpar);
- do {
- pos = index(currpath, '/');
- if (pos)
- *pos = 0;
+ for (subdir = path, dirsep = 0; subdir[dirsep]; subdir += dirsep) {
+ dirsep = strcspn(subdir, "/\\");
+ if (!dirsep) {
+ subdir++;
+ continue;
+ }
- /* printf("cp=%s\n", currpath); */
- mkdir(currpath, mode);
- ret = chdir(currpath);
+ c = subdir[dirsep];
+ subdir[dirsep] = 0;
+ r = realpath(path, rsub);
+ sublen = strlen(rsub);
+ if (NULL == r) {
+ if(ENOENT != errno) {
+ fprintf(stderr, "realpath(%s) failed: %s\n",
+ path, strerror(errno));
+ goto done;
+ }
+ } else if (sublen < parlen || strncmp(rpar, rsub, parlen)) {
+ fprintf(stderr, "Abort: %s is outside %s\n", dirpath,
+ parent);
+ goto done;
+ }
+ if(-1 == mkdir(path, mode) && EEXIST != errno) {
+ fprintf(stderr, "mkdir(%s): %s\n", path,
+ strerror(errno));
+ goto done;
+ }
+ subdir[dirsep] = c;
+ }
+ ret = 0;
- if (pos)
- currpath = pos + 1;
- } while (pos && !ret && strlen(currpath));
-
- chdir(cwd);
- free(path);
-
+done:
+ if (path)
+ free(path);
return ret;
}
Index: util/lar/extract.c
===================================================================
--- util/lar/extract.c (revision 447)
+++ util/lar/extract.c (working copy)
@@ -119,7 +119,7 @@
if (pos) {
pos[1] = 0;
/* printf("Pathname %s\n",pathname); */
- mkdirp(pathname, 0755);
+ mkdirp(".", pathname, 0755);
}
free(pathname);
Index: util/lar/lib.h
===================================================================
--- util/lar/lib.h (revision 447)
+++ util/lar/lib.h (working copy)
@@ -41,7 +41,7 @@
char *get_bootblock(void);
/* prototypes for lib.c functions */
-int mkdirp(const char *dirpath, mode_t mode);
+int mkdirp(const char *parent, const char *dirpath, mode_t mode);
int add_files(const char *name);
int add_file_or_directory(const char *name);
More information about the coreboot
mailing list