Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,41 @@ gchar *dir_parent(gchar * p)
}
return NULL;
}

/**
* Make sure a path exists
*/

void dir_mkpath(gchar *p)
{
gchar *parent;

parent = dir_parent(p);

if (parent && (parent[0] == 0)) {
msgd(__func__, __LINE__, _("Reached / while trying to create path, bailing out."));
g_free(parent);
return;
}

#if DEBUG
msgd(__func__, __LINE__, _("Creating skeleton directory `%s\'"), parent);
#endif

struct stat *st = g_malloc(sizeof(struct stat));

if (stat(parent, st) != 0) {
/* Directory does not exist. EEXIST for race condition */
if (mkdir(parent, 0700) != 0 && errno != EEXIST) {
dir_mkpath(parent);
if (mkdir(parent, 0700) != 0 && errno != EEXIST)
msgd(__func__, __LINE__, _("Failed to create `%s\'"), parent);
}
}
else if (!S_ISDIR(st->st_mode)) {
msgd(__func__, __LINE__, _("%s\': already exists and not a directory"), parent);
}

g_free(st);
g_free(parent);
}
85 changes: 80 additions & 5 deletions fs-up.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,33 @@ mk_dev(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
return FALSE;

if (mknod(e->f_name, e->f_mode, e->f_rdev) == -1) {
if (errno == EACCES) {
if ( errno == ENOENT ) {
// A path element does not exist, this is probably a -R dump
// Create path with default perms, dir entry itself will appear later
// and set things right regarding perms/ownership
dir_mkpath(e->f_name);

// Retry mknod
if (mknod(e->f_name, e->f_mode, e->f_rdev) == -1) {
msgd(__func__, __LINE__,
_("Failed to make device `%s\': %s"),
e->f_name, strerror(errno));
return FALSE;
}
} else if (errno == EACCES) {
parent = dir_parent(e->f_name);
st = dir_write(parent);
if (mknod(e->f_name, e->f_mode, e->f_rdev) == -1) {
msgd(__func__, __LINE__,
_("Failed to make device `%s\': %s"),
e->f_name, strerror(errno));
dir_restore(parent, st);
g_free(st);
g_free(parent);
return FALSE;
}
dir_restore(parent, st);
g_free(st);
g_free(parent);
} else {
msgd(__func__, __LINE__,
Expand All @@ -134,18 +149,33 @@ mk_sock(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
return FALSE;

if (mkfifo(e->f_name, e->f_mode) == -1) {
if (errno == EACCES) {
if ( errno == ENOENT ) {
// A path element does not exist, this is probably a -R dump
// Create path with default perms, dir entry itself will appear later
// and set things right regarding perms/ownership
dir_mkpath(e->f_name);

// Retry fifio
if (mkfifo(e->f_name, e->f_mode) == -1) {
msgd(__func__, __LINE__,
_("Failed to make socket `%s\': %s"),
e->f_name, strerror(errno));
return FALSE;
}
} else if (errno == EACCES) {
parent = dir_parent(e->f_name);
st = dir_write(parent);
if (mkfifo(e->f_name, e->f_mode) == -1) {
msgd(__func__, __LINE__,
_("Failed to make socket `%s\': %s"),
e->f_name, strerror(errno));
dir_restore(parent, st);
g_free(st);
g_free(parent);
return FALSE;
}
dir_restore(parent, st);
g_free(st);
g_free(parent);
} else {
msgd(__func__, __LINE__,
Expand Down Expand Up @@ -174,7 +204,20 @@ mk_link(struct rdup *e, char *p, GHashTable * uidhash, GHashTable * gidhash)
/* symlink */
if (S_ISLNK(e->f_mode)) {
if (symlink(e->f_target, e->f_name) == -1) {
if (errno == EACCES) {
if ( errno == ENOENT ) {
// A path element does not exist, this is probably a -R dump
// Create path with default perms, dir entry itself will appear later
// and set things right regarding perms/ownership
dir_mkpath(e->f_name);

// Retry symlink
if (symlink(e->f_target, e->f_name) == -1) {
msgd(__func__, __LINE__,
_("Failed to make symlink `%s -> %s\': %s"),
e->f_name, e->f_target, strerror(errno));
return FALSE;
}
} else if (errno == EACCES) {
parent = dir_parent(e->f_name);
st = dir_write(parent);
if (symlink(e->f_target, e->f_name) == -1) {
Expand All @@ -184,10 +227,12 @@ mk_link(struct rdup *e, char *p, GHashTable * uidhash, GHashTable * gidhash)
e->f_name, e->f_target,
strerror(errno));
dir_restore(parent, st);
g_free(st);
g_free(parent);
return FALSE;
}
dir_restore(parent, st);
g_free(st);
g_free(parent);
} else {
msgd(__func__, __LINE__,
Expand Down Expand Up @@ -236,17 +281,32 @@ mk_reg(FILE * in, struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
}
}
if (!opt_dry && !(out = fopen(e->f_name, "w"))) {
if (errno == EACCES) {
if ( errno == ENOENT ) {
// A path element does not exist, this is probably a -R dump
// Create path with default perms, dir entry itself will appear later
// and set things right regarding perms/ownership
dir_mkpath(e->f_name);

// Reopen file now
if (!(out = fopen(e->f_name, "w"))) {
msgd(__func__, __LINE__,
_("ENOENT file `%s\': %s"),
e->f_name, strerror(errno));
ok = FALSE;
}
} else if (errno == EACCES) {
parent = dir_parent(e->f_name);
st = dir_write(parent);
if (!(out = fopen(e->f_name, "w"))) {
msgd(__func__, __LINE__,
_("Failed to open file `%s\': %s"),
e->f_name, strerror(errno));
g_free(st);
g_free(parent);
ok = FALSE;
}
dir_restore(parent, st);
g_free(st);
g_free(parent);
} else {
msgd(__func__, __LINE__,
Expand Down Expand Up @@ -320,7 +380,20 @@ mk_dir(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
/* nothing there */

if (mkdir(e->f_name, e->f_mode) == -1) {
if (errno == EACCES) {
if ( errno == ENOENT ) {
// A path element does not exist, this is probably a -R dump
// Create path with default perms, dir entry itself will appear later
// and set things right regarding perms/ownership
dir_mkpath(e->f_name);

// Retry mkdir
if (mkdir(e->f_name, e->f_mode) == -1) {
msgd(__func__, __LINE__,
_("Failed to create directory `%s\': %s"),
e->f_name, strerror(errno));
return FALSE;
}
} else if (errno == EACCES) {
/* make parent dir writable, and try again */
parent = dir_parent(e->f_name);
#ifdef DEBUG
Expand All @@ -336,10 +409,12 @@ mk_dir(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
_("Failed to create directory `%s\': %s"),
e->f_name, strerror(errno));
dir_restore(parent, s);
g_free(s);
g_free(parent);
return FALSE;
}
dir_restore(parent, s);
g_free(s);
g_free(parent);
} else {
msgd(__func__, __LINE__,
Expand Down
2 changes: 2 additions & 0 deletions rdup-up.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ int mkpath(const char *, mode_t);
struct stat * dir_write(gchar *);
void dir_restore(gchar *, struct stat *);
gchar *dir_parent(gchar *);
void dir_mkpath(gchar *);


/* chown.c */
void chown_write(gchar *dir, gchar *base, uid_t u, gchar *user, gid_t g, gchar *group);
Expand Down