Пример #1
0
Файл: fs-up.c Проект: dpc/rdup
static gboolean
mk_dir(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
{
	struct stat *s;
	struct stat st;
	gchar *parent;

	if (opt_dry)
		return TRUE;

	if (lstat(e->f_name, &st) == 0) {
		if (S_ISDIR(st.st_mode)) {
#if 0
			msgd(__func__, __LINE__,
			     _("Updating current dir `%s\'"), e->f_name);
#endif				/* DEBUG */
			/* some dir is here - update the perms and ownership */
			mk_meta(e, uidhash, gidhash);
			return TRUE;
		}
	}
	/* nothing there */

	if (mkdir(e->f_name, e->f_mode) == -1) {
		if (errno == EACCES) {
			/* make parent dir writable, and try again */
			parent = dir_parent(e->f_name);
#ifdef DEBUG
			msgd(__func__, __LINE__, _("EACCES for `%s\'"), parent);
#endif				/* DEBUG */
			s = dir_write(parent);
			if (!s)
				msgd(__func__, __LINE__,
				     _("Failed to make parent writable"));

			if (mkdir(e->f_name, e->f_mode) == -1) {
				msgd(__func__, __LINE__,
				     _("Failed to create directory `%s\': %s"),
				     e->f_name, strerror(errno));
				dir_restore(parent, s);
				g_free(parent);
				return FALSE;
			}
			dir_restore(parent, s);
			g_free(parent);
		} else {
			msgd(__func__, __LINE__,
			     _("Failed to create directory `%s\': %s"),
			     e->f_name, strerror(errno));
			return FALSE;
		}
	}
	mk_meta(e, uidhash, gidhash);
	return TRUE;
}
Пример #2
0
Файл: fs-up.c Проект: dpc/rdup
static gboolean
mk_link(struct rdup *e, char *p, GHashTable * uidhash, GHashTable * gidhash)
{
	struct stat *st;
	gchar *t;
	gchar *parent;

	if (opt_dry)
		return TRUE;

	if (!rm(e->f_name))
		return FALSE;

	/* symlink */
	if (S_ISLNK(e->f_mode)) {
		if (symlink(e->f_target, e->f_name) == -1) {
			if (errno == EACCES) {
				parent = dir_parent(e->f_name);
				st = dir_write(parent);
				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));
					dir_restore(parent, st);
					g_free(parent);
					return FALSE;
				}
				dir_restore(parent, st);
				g_free(parent);
			} else {
				msgd(__func__, __LINE__,
				     _
				     ("Failed to make symlink `%s -> %s\': %s"),
				     e->f_name, e->f_target, strerror(errno));
				return FALSE;
			}
		}
		mk_chown(e, uidhash, gidhash);
		return TRUE;
	}

	/* hardlink */
	/* target must also fall in backup dir */
	t = g_strdup_printf("%s%s", p, e->f_target);
	e->f_target = t;
	hlink_list = g_slist_append(hlink_list, entry_dup(e));
	return TRUE;
}
Пример #3
0
Файл: fs-up.c Проект: dpc/rdup
static gboolean
mk_chown(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
{
	uid_t u;
	gid_t g;
	u = lookup_uid(uidhash, e->f_user, e->f_uid);
	g = lookup_gid(gidhash, e->f_group, e->f_gid);

	if (lchown(e->f_name, u, g) == -1) {
		if (opt_chown) {
			/* chown failed, use and create ._rdup_. - file, it that fails too
			 * we're out of luck - so we don't care about the return value */
			if (S_ISDIR(e->f_mode)) {
				chown_write(e->f_name, NULL, e->f_uid,
					    e->f_user, e->f_gid, e->f_group);
			} else {
				chown_write(dirname(e->f_name),
					    basename(e->f_name), e->f_uid,
					    e->f_user, e->f_gid, e->f_group);
			}
		} else {
			if (!opt_quiet) {
				msgd(__func__, __LINE__,
				     _("Failed to chown `%s\': %s"), e->f_name,
				     strerror(errno));
			}
		}
	}
	return TRUE;
}
Пример #4
0
Файл: dir.c Проект: tyll/rdup
void
dir_restore(gchar *p, struct stat *s)
{
	if (!s || !p)
		return;
	/* restore perms - assumes *s has not be f*cked up */
	if (chmod(p, s->st_mode & 07777) == -1) {
		msgd(__func__, __LINE__,_("Failed to restore permissions `%s\': %s"), p, strerror(errno));
	}
}
Пример #5
0
Файл: fs-up.c Проект: dpc/rdup
static gboolean mk_time(struct rdup *e)
{
	struct utimbuf ut;
	/* we don't carry the a_time, how cares anyway with noatime? */
	ut.actime = ut.modtime = e->f_mtime;

	if (utime(e->f_name, &ut) == -1)
		msgd(__func__, __LINE__, _("Failed to set mtime '%s\': %s"),
		     e->f_name, strerror(errno));
	return TRUE;
}
Пример #6
0
Файл: fs-up.c Проект: dpc/rdup
/* Create the remaining hardlinks in the target directory */
gboolean mk_hlink(GSList * h)
{
	struct rdup *e;
	GSList *p;
	struct stat *st;
	gchar *parent;

	if (opt_dry)
		return TRUE;

	for (p = g_slist_nth(h, 0); p; p = p->next) {
		e = (struct rdup *)p->data;
		if (link(e->f_target, e->f_name) == -1) {
			if (errno == EACCES) {
				parent = dir_parent(e->f_name);
				st = dir_write(parent);
				if (link(e->f_target, e->f_name) == -1) {
					msgd(__func__, __LINE__,
					     _
					     ("Failed to create hardlink `%s -> %s\': %s"),
					     e->f_name, e->f_target,
					     strerror(errno));
					dir_restore(parent, st);
					g_free(parent);
					return FALSE;
				}
				dir_restore(parent, st);
				g_free(parent);
				return TRUE;
			} else {
				msgd(__func__, __LINE__,
				     _
				     ("Failed to create hardlink `%s -> %s\': %s"),
				     e->f_name, e->f_target, strerror(errno));
				return FALSE;
			}
		}
		entry_free(e);
	}
	return TRUE;
}
Пример #7
0
/* this implements the -r options, strip opt_strip_path from each name */
void strippathname(struct rdup *e)
{
	gchar *where;
	guint len;

	if (!e->f_name)
		return;

	/* the other way around, if the path is a prefix of the prefix
	 * we should discard the entry. But only is the path we are looking
	 * at is LONGER than the prefix
	 */
	(void)pathlabel(e);
#ifdef DEBUG
	msgd(__func__, __LINE__, _("Label %d, strippathlen %d\n"), pathlabel(e),
	     opt_path_strip_len);
#endif				/* DEBUG */
/*	if (pathlabel(e) > opt_path_strip_len) { */
	if (g_str_has_prefix(opt_path_strip, e->f_name)) {
		e->f_name = NULL;
		e->f_name_size = 0;
		return;
	}
/*	} */

	if (g_str_has_prefix(e->f_name, opt_path_strip) == FALSE)
		return;

	len = strlen(opt_path_strip) - 1;	/* -1: discard the trailing slash */
	where = e->f_name + len;

	/* string starts with opt_path_strip, so we can just jump
	 * into e->f_name[strlen of opt_path_strip] and discard
	 * everything before
	 */
	memmove(e->f_name, where, e->f_name_size - len);
	e->f_name_size -= len;
	e->f_name[e->f_name_size] = '\0';

	if (S_ISLNK(e->f_mode) || e->f_lnk == 1)
		e->f_size -= len;

	/* hardlinks need to get the same treatment */
	if (e->f_lnk == 1) {
		if (g_str_has_prefix(e->f_target, opt_path_strip) == TRUE) {
			where = e->f_target + len;
			memmove(e->f_target, where, strlen(e->f_target) - len);
			e->f_size -= len;
			e->f_target[e->f_size] = '\0';
		}
	}
	return;
}
Пример #8
0
Файл: dir.c Проект: tyll/rdup
struct stat *
dir_write(gchar *p)
{
	 /* chmod +w . && rm $file && chmod -w # and hope for the best */
	if (!p)
		return NULL;

	struct stat *s = g_malloc(sizeof(struct stat));
#ifdef DEBUG
	msgd(__func__, __LINE__,_("Making directory writable `%s\'"), p);
#endif /* DEBUG */

	if (stat(p, s) == -1)
		return NULL;

	/* make it writable, assume we are the OWNER */
	if (chmod(p, s->st_mode | S_IWUSR) == -1) {
		msgd(__func__, __LINE__,_("Failed to make directory writeable `%s\': %s"), p, strerror(errno));
	}
	return s;
}
Пример #9
0
Файл: fs-up.c Проект: dpc/rdup
static gboolean
mk_dev(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
{
	gchar *parent;
	struct stat *st;

	if (opt_dry)
		return TRUE;

	if (!rm(e->f_name))
		return FALSE;

	if (mknod(e->f_name, e->f_mode, e->f_rdev) == -1) {
		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(parent);
				return FALSE;
			}
			dir_restore(parent, st);
			g_free(parent);
		} else {
			msgd(__func__, __LINE__,
			     _("Failed to make device `%s\': %s"), e->f_name,
			     strerror(errno));
			return FALSE;
		}
	}
	mk_meta(e, uidhash, gidhash);
	return TRUE;
}
Пример #10
0
Файл: fs-up.c Проект: dpc/rdup
static gboolean
mk_reg(FILE * in, struct rdup *e, GHashTable * uidhash, GHashTable * gidhash)
{
	FILE *out = NULL;
	char *buf;
	gchar *parent;
	size_t bytes;
	gboolean ok = TRUE;
	gboolean old_dry = opt_dry;
	struct stat *st;

	/* with opt_dry we can't just return TRUE; as we may
	 * need to suck in the file's content - which is thrown
	 * away in that case */

	if (!e->f_name) {
		/* fake an opt_dry */
		opt_dry = TRUE;
	}

	if (!opt_dry) {
		if (!rm(e->f_name)) {
			opt_dry = old_dry;
			return FALSE;
		}
	}
	if (!opt_dry && !(out = fopen(e->f_name, "w"))) {
		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(parent);
				ok = FALSE;
			}
			dir_restore(parent, st);
			g_free(parent);
		} else {
			msgd(__func__, __LINE__,
			     _("Failed to open file `%s\': %s"), e->f_name,
			     strerror(errno));
			ok = FALSE;
		}
	}

	/* we need to read the input to not upset
	 * the flow into rdup-up, but we are not
	 * creating anything when opt_dry is active
	 */
	buf = g_malloc(BUFSIZE + 1);
	while ((bytes = block_in_header(in)) > 0) {
		if (block_in(in, bytes, buf) == -1) {
			if (out)
				fclose(out);
			opt_dry = old_dry;
			g_free(buf);
			return FALSE;
		}
		if (ok && !opt_dry) {
			if (fwrite(buf, sizeof(char), bytes, out) != bytes) {
				msgd(__func__, __LINE__,
				     _("Write failure `%s\': %s"), e->f_name,
				     strerror(errno));
				if (out)
					fclose(out);
				opt_dry = old_dry;
				g_free(buf);
				return FALSE;
			}
		}
	}
	g_free(buf);
	if (ok && out)
		fclose(out);

	if (ok && !opt_dry)
		mk_meta(e, uidhash, gidhash);

#ifdef DEBUG
	msgd(__func__, __LINE__, "Wrote file `%s\'", e->f_name);
#endif				/* DEBUG */
	opt_dry = old_dry;
	return TRUE;
}
Пример #11
0
Файл: rm.c Проект: tyll/rdup
gboolean
rm(gchar *p)
{
	int ret;
	gchar *dirp, *q;
	gchar *parent;
	GDir *d;
	struct stat st;
	struct stat *st2;

	if (opt_dry || !p)
		return TRUE;	/* noop */

	if (lstat(p, &st) == -1) {
		if (opt_verbose > 0 && errno != ENOENT)
			msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno));
		return TRUE;    /* noop */
	}

	if (S_ISDIR(st.st_mode)) {
		ret = remove(p);
		if (ret == -1) {
			switch(errno) {
				case ENOTEMPTY:
					/* recursive into this dir and do our bidding */
					if (!(d = g_dir_open(p, 0, NULL))) {
						msgd(__func__, __LINE__,_("Failed to open directory `%s\': %s"), p, strerror(errno));
						return FALSE;
					}
					while ( (dirp = (gchar*)g_dir_read_name(d))) {
						dirp = g_strdup_printf("%s/%s", p, dirp);
						rm(dirp);
						g_free(dirp);
					}
					g_dir_close(d);
					/* dir should be empty by now */
					if ((ret = remove(p)) == -1)
						msgd(__func__, __LINE__,_("Failed to remove directory `%s\': %s"),
								p, strerror(errno));
					return TRUE;
				
				case EACCES:
					/* no write to dir, make writable */
					parent = dir_parent(p);
					st2 = dir_write(parent);
					if (remove(p) == -1) {
						msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"),
								p, strerror(errno));
						dir_restore(parent, st2);
						g_free(parent);
						return FALSE;
					}
					dir_restore(parent, st2);
					g_free(parent);
					return TRUE;

				default:
					/* not ENOEMPTY */
					msgd(__func__, __LINE__,_("Failed to remove directory `%s\': %s"), p, strerror(errno));
					return FALSE;
			}
		}
		return TRUE;
	}

	/* dirs are now handled */

	if (remove(p) == -1) {
		switch(errno) {
			case EACCES:
				/* we have no access, ok ... */
				q = g_strdup(p);
				parent = dirname(q);
				st2 = dir_write(parent);
				if (remove(p) == -1) {
					msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno));
					dir_restore(parent, st2);
					g_free(q);
					return FALSE;
				}
				dir_restore(parent, st2);
				g_free(q);
				return TRUE;

			case EPERM:
				/* no write on file, reuse st - and why is this needed again? */
				/* this is dead code ... */
				stat(p, &st);
				chmod(p, st.st_mode | S_IWUSR);
				if (remove(p) == -1) {
					msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"),
							p, strerror(errno));
					chmod(p, st.st_mode); /* is this usefull then? */
					return FALSE;
				}
				return TRUE;	
		}
		
		msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno));
		return FALSE;
	}
	return TRUE;
}