Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Handle all flags preventing file manipulation
Baptiste Daroussin committed 11 years ago
commit 7fec3fedf4abc10b2e769859e6587f6e9a903938
parent 983522f
2 files changed +38 -1
modified libpkg/pkg_add.c
@@ -42,6 +42,9 @@
#include "private/pkg.h"
#include "private/pkgdb.h"

+
#define NOCHANGESFLAGS	(UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
+

+

static const unsigned char litchar[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

@@ -254,13 +257,29 @@ do_extract(struct archive *a, struct archive_entry *ae, const char *location,

		/* Rename old file */
		if (renamed) {
+
			bool old = false;
+

			pkg_debug(1, "Renaming %s -> %s", rpath, pathname);
+
			if (aest->st_flags & NOCHANGESFLAGS)
+
				chflags(rpath, aest->st_flags & ~NOCHANGESFLAGS);
+

+
			if (lstat(pathname, &st) != -1) {
+
				old = true;
+
				if (st.st_flags & NOCHANGESFLAGS)
+
					chflags(pathname, aest->st_flags & ~NOCHANGESFLAGS);
+
			}
+

			if (rename(rpath, pathname) == -1) {
+
				/* restore flags */
+
				if (old)
+
					chflags(pathname, st.st_flags);
				pkg_emit_error("cannot rename %s to %s: %s", rpath, pathname,
					strerror(errno));
				retcode = EPKG_FATAL;
				goto cleanup;
			}
+
			/* Restore flags on the final file */
+
			chflags(pathname, aest->st_flags);
		}

		if (string_end_with(pathname, ".pkgnew"))
@@ -280,8 +299,11 @@ cleanup:
	pkg_emit_progress_tick(nfiles, nfiles);
	pkg_emit_extract_finished(pkg);

-
	if (renamed && retcode == EPKG_FATAL)
+
	if (renamed && retcode == EPKG_FATAL) {
+
		if (aest->st_flags & NOCHANGESFLAGS)
+
			chflags(rpath, aest->st_flags & ~NOCHANGESFLAGS);
		unlink(rpath);
+
	}

	return (retcode);
}
modified libpkg/pkg_delete.c
@@ -43,6 +43,8 @@
#include "private/pkgdb.h"
#include "private/utils.h"

+
#define NOCHANGESFLAGS	(UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
+

int
pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags)
{
@@ -161,6 +163,7 @@ rmdir_p(struct pkgdb *db, struct pkg *pkg, char *dir, const char *prefix_r)
	int64_t cnt;
	char fullpath[MAXPATHLEN];
	size_t len;
+
	struct stat st;

	len = snprintf(fullpath, sizeof(fullpath), "/%s", dir);
	while (fullpath[len -1] == '/') {
@@ -184,6 +187,12 @@ rmdir_p(struct pkgdb *db, struct pkg *pkg, char *dir, const char *prefix_r)
		return;

	pkg_debug(1, "removing directory %s", fullpath);
+
	if (fstatat(pkg->rootfd, dir, &st, AT_SYMLINK_NOFOLLOW) != -1)
+
		if (st.st_flags & NOCHANGESFLAGS)
+
			chflagsat(pkg->rootfd, dir,
+
			    st.st_flags & ~NOCHANGESFLAGS,
+
			    AT_SYMLINK_NOFOLLOW);
+

	if (unlinkat(pkg->rootfd, dir, AT_REMOVEDIR) == -1) {
		if (errno != ENOTEMPTY && errno != EBUSY)
			pkg_emit_errno("unlinkat", dir);
@@ -267,6 +276,12 @@ pkg_delete_file(struct pkg *pkg, struct pkg_file *file, unsigned force)
		}
	}

+
	if (fstatat(pkg->rootfd, path, &st, AT_SYMLINK_NOFOLLOW) != -1)
+
		if (st.st_flags & NOCHANGESFLAGS)
+
			chflagsat(pkg->rootfd, path,
+
			    st.st_flags & ~NOCHANGESFLAGS,
+
			    AT_SYMLINK_NOFOLLOW);
+

	if (unlinkat(pkg->rootfd, path, 0) == -1) {
		if (force < 2)
			pkg_emit_errno("unlinkat", path);