-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
track file mode and ownership in files.plist #541
base: master
Are you sure you want to change the base?
Changes from all commits
962546f
6423485
15a370b
7125a81
851b1de
0ec41f5
cbcc350
aefb164
28fe8de
aab32fe
ea189d1
754fae2
6d46066
02f7bcd
bc43563
e95dbf8
7bc4884
75fdf6f
5a40d21
4bc0224
8f483c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,9 @@ | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
#define _DEFAULT_SOURCE | ||
|
||
#include <sys/types.h> | ||
#include <sys/param.h> | ||
#include <sys/stat.h> | ||
|
@@ -41,6 +44,7 @@ | |
#include <libgen.h> | ||
#include <locale.h> | ||
#include <dirent.h> | ||
#include <fnmatch.h> | ||
|
||
#include <xbps.h> | ||
#include "queue.h" | ||
|
@@ -66,6 +70,7 @@ struct xentry { | |
char *file, *target; | ||
char sha256[XBPS_SHA256_SIZE]; | ||
ino_t inode; | ||
mode_t mode; | ||
}; | ||
|
||
static TAILQ_HEAD(xentry_head, xentry) xentry_list = | ||
|
@@ -109,6 +114,9 @@ usage(bool fail) | |
" 'vi:/usr/bin/vi:/usr/bin/vim foo:/usr/bin/foo:/usr/bin/blah'\n" | ||
" --build-options A string with the used build options\n" | ||
" --compression Compression format: none, gzip, bzip2, lz4, xz, zstd (default)\n" | ||
" --chown Set the ownership of files and directories.\n" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this doesn't handle paths with spaces... maybe accepting the argument multiple times would be better, or is this not a concern? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. something else to consider: should |
||
" This expects a blank-separated list of <pattern>:<user>:<group>,\n" | ||
" where '<pattern>' is an fnmatch(3) pattern.\n" | ||
" --shlib-provides List of provided shared libraries (blank separated list,\n" | ||
" e.g 'libfoo.so.1 libblah.so.2')\n" | ||
" --shlib-requires List of required shared libraries (blank separated list,\n" | ||
|
@@ -245,7 +253,6 @@ process_one_alternative(const char *altgrname, const char *val) | |
} | ||
} | ||
|
||
|
||
static void | ||
process_dict_of_arrays(const char *key UNUSED, const char *val) | ||
{ | ||
|
@@ -281,6 +288,71 @@ process_dict_of_arrays(const char *key UNUSED, const char *val) | |
free(args); | ||
} | ||
|
||
static bool | ||
process_chown_pattern(const char *key, const char *fpat, const char *user, const char *group) | ||
{ | ||
xbps_object_iterator_t iter; | ||
xbps_object_t obj; | ||
const char *fname; | ||
bool match = false; | ||
|
||
if ((iter = xbps_array_iter_from_dict(pkg_filesd, key)) != NULL) { | ||
while ((obj = xbps_object_iterator_next(iter))) { | ||
xbps_dictionary_get_cstring_nocopy(obj, "file", &fname); | ||
if (fnmatch(fpat, fname, 0) == 0) { | ||
match = true; | ||
if (user != NULL) | ||
xbps_dictionary_set_cstring(obj, "user", user); | ||
if (group != NULL) | ||
xbps_dictionary_set_cstring(obj, "group", group); | ||
} | ||
} | ||
} | ||
return match; | ||
} | ||
|
||
static void | ||
process_chown_patterns(const char *val) | ||
{ | ||
char *raw, *itm, *fpat, *user, *group; | ||
|
||
if (val == NULL) | ||
return; | ||
|
||
raw = strdup(val); | ||
|
||
while ((itm = strsep(&raw, " "))) { | ||
fpat = strsep(&itm, ":"); | ||
if (fpat == NULL || strlen(fpat) == 0) { | ||
xbps_warn_printf("%s: skipping chown pattern `:%s': empty pattern\n", _PROGNAME, itm); | ||
continue; | ||
} | ||
|
||
user = strsep(&itm, ":"); | ||
if (strlen(user) == 0 || strcmp(user, "root") == 0) | ||
user = NULL; | ||
group = strsep(&itm, ":"); | ||
if (strlen(group) == 0 || strcmp(group, "root") == 0) | ||
group = NULL; | ||
|
||
if (itm != NULL) | ||
xbps_warn_printf("%s: chown pattern contains extra data: %s\n", _PROGNAME, itm); | ||
|
||
if (user == NULL && group == NULL) { | ||
xbps_warn_printf("%s: skipping chown pattern `%s': user and group empty or root\n", _PROGNAME, fpat); | ||
continue; | ||
} | ||
|
||
if (!(process_chown_pattern("dirs", fpat, user, group) || | ||
process_chown_pattern("files", fpat, user, group) || | ||
process_chown_pattern("links", fpat, user, group))) { | ||
xbps_warn_printf("%s: chown pattern %s matched nothing\n", _PROGNAME, fpat); | ||
} | ||
} | ||
|
||
free(raw); | ||
} | ||
|
||
static void | ||
process_file(const char *file, const char *key) | ||
{ | ||
|
@@ -396,6 +468,10 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED | |
goto out; | ||
} | ||
|
||
/* symlinks don't have a mode on linux */ | ||
if (!S_ISLNK(sb->st_mode)) | ||
xe->mode = sb->st_mode; | ||
|
||
if (S_ISLNK(sb->st_mode)) { | ||
char buf[PATH_MAX]; | ||
ssize_t len; | ||
|
@@ -530,7 +606,6 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED | |
xbps_dictionary_set_uint64(fileinfo, "inode", sb->st_ino); | ||
xe->inode = sb->st_ino; | ||
xe->size = (uint64_t)sb->st_size; | ||
|
||
} else if (S_ISDIR(sb->st_mode)) { | ||
/* directory */ | ||
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "dirs"); | ||
|
@@ -650,6 +725,8 @@ process_xentry(enum entry_type type, const char *mutable_files) | |
xbps_dictionary_set_cstring(d, "sha256", xe->sha256); | ||
if (xe->size) | ||
xbps_dictionary_set_uint64(d, "size", xe->size); | ||
if (xe->mode) | ||
xbps_dictionary_set_uint32(d, "mode", xe->mode); | ||
|
||
xbps_array_add(a, d); | ||
xbps_object_release(d); | ||
|
@@ -832,6 +909,7 @@ main(int argc, char **argv) | |
{ "build-options", required_argument, NULL, '2' }, | ||
{ "built-with", required_argument, NULL, 'B' }, | ||
{ "changelog", required_argument, NULL, 'c'}, | ||
{ "chown", required_argument, NULL, '6'}, | ||
{ "compression", required_argument, NULL, '3' }, | ||
{ "config-files", required_argument, NULL, 'F' }, | ||
{ "conflicts", required_argument, NULL, 'C' }, | ||
|
@@ -865,7 +943,7 @@ main(int argc, char **argv) | |
const char *provides, *pkgver, *replaces, *reverts, *desc, *ldesc; | ||
const char *arch, *config_files, *mutable_files, *version, *changelog; | ||
const char *buildopts, *shlib_provides, *shlib_requires, *alternatives; | ||
const char *compression, *tags = NULL, *srcrevs = NULL, *sourcepkg = NULL; | ||
const char *compression, *tags = NULL, *srcrevs = NULL, *sourcepkg = NULL, *chownlst; | ||
char pkgname[XBPS_NAME_SIZE], *binpkg, *tname, *p, cwd[PATH_MAX-1]; | ||
bool quiet = false, preserve = false; | ||
int c, pkg_fd; | ||
|
@@ -874,7 +952,7 @@ main(int argc, char **argv) | |
arch = conflicts = deps = homepage = license = maint = compression = NULL; | ||
provides = pkgver = replaces = reverts = desc = ldesc = bwith = NULL; | ||
buildopts = config_files = mutable_files = shlib_provides = NULL; | ||
alternatives = shlib_requires = changelog = NULL; | ||
alternatives = shlib_requires = changelog = chownlst = NULL; | ||
|
||
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { | ||
if (optarg && strcmp(optarg, "") == 0) | ||
|
@@ -965,6 +1043,9 @@ main(int argc, char **argv) | |
case '5': | ||
sourcepkg = optarg; | ||
break; | ||
case '6': | ||
chownlst = optarg; | ||
break; | ||
case '?': | ||
default: | ||
usage(true); | ||
|
@@ -1081,6 +1162,7 @@ main(int argc, char **argv) | |
die("xbps_dictionary_create"); | ||
|
||
process_destdir(mutable_files); | ||
process_chown_patterns(chownlst); | ||
|
||
/* Back to original cwd after file tree walk processing */ | ||
if (chdir(p) == -1) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#include <assert.h> | ||
#include <errno.h> | ||
#include <string.h> | ||
#include <sys/stat.h> | ||
|
||
#include "defs.h" | ||
|
||
int | ||
file_mode_check(const char *file, const mode_t mode) { | ||
struct stat sb; | ||
|
||
assert(file != NULL); | ||
assert(mode); | ||
|
||
if (lstat(file, &sb) == -1) | ||
return -errno; | ||
|
||
if (sb.st_mode != mode) | ||
return ERANGE; | ||
|
||
return 0; | ||
} | ||
|
||
int | ||
file_user_check(struct idtree * idt, const char *file, const char *user) { | ||
struct stat sb; | ||
char *act_user; | ||
|
||
assert(file != NULL); | ||
assert(user != NULL); | ||
|
||
if (lstat(file, &sb) == -1) | ||
return -errno; | ||
|
||
act_user = idtree_username(idt, sb.st_uid); | ||
return strcmp(user, act_user) == 0 ? 0 : ERANGE; | ||
} | ||
|
||
int | ||
file_group_check(struct idtree * idt, const char *file, const char *grp) { | ||
struct stat sb; | ||
char *act_grp; | ||
|
||
assert(file != NULL); | ||
assert(grp != NULL); | ||
|
||
if (lstat(file, &sb) == -1) | ||
return -errno; | ||
|
||
act_grp = idtree_groupname(idt, sb.st_gid); | ||
return strcmp(grp, act_grp) == 0 ? 0 : ERANGE; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needed for
strsep()
. is this the right spot to put it?