Skip to content
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

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
962546f
lib/compat/humanize_number.c: switch to freebsd version
Duncaen Feb 21, 2023
6423485
lib: add xbps_fmt* functions for string formatting
Duncaen Feb 20, 2023
15a370b
bin/xbps-query: add -F/--format flag
Duncaen Feb 20, 2023
7125a81
tests: add tests for xbps_fmt* functions
Duncaen Feb 21, 2023
851b1de
lib/format.c: new humanize format !humanize[ ][.][width][minscale[max…
Duncaen Feb 21, 2023
0ec41f5
bin/xbps-query: document format flag
Duncaen Feb 21, 2023
cbcc350
lib/format.c: split/cleanup code
Duncaen Mar 10, 2023
aefb164
lib/format.c: change escaped [{}] to \\[{}]
Duncaen Mar 10, 2023
28fe8de
lib/format.c: add some more escape sequences
Duncaen Mar 10, 2023
aab32fe
bin/xbps-query: update/clean format documentation
Duncaen Mar 10, 2023
ea189d1
bin/xbps-query: fix humanize "i" SI prefixs documentation
Duncaen Mar 10, 2023
754fae2
lib/format.c: refactor a bit
Duncaen Mar 14, 2023
6d46066
lib/format.c: add optional default to format string variables
Duncaen Mar 14, 2023
02f7bcd
lib/format.c: simplify escape characters
Duncaen Mar 14, 2023
bc43563
lib/format: add \e escape, fix typos in format spec, remove dbg print
classabbyamp Mar 15, 2023
e95dbf8
lib/compat: add strmode() and xbps_strmode()
classabbyamp Feb 20, 2023
7bc4884
lib/format.c: implement tostrmode()
classabbyamp Mar 14, 2023
75fdf6f
bin/xbps-create: record file mode, owner, and group
classabbyamp Feb 20, 2023
5a40d21
bin/xbps-pkgdb: check file and symlink owners & perms
classabbyamp Feb 20, 2023
4bc0224
bin/xbps-query: add --long for -f to show file perms, owner, size
classabbyamp Feb 20, 2023
8f483c6
tests/xbps/xbps-query: add tests for [--long] -f
classabbyamp Mar 16, 2023
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
26 changes: 26 additions & 0 deletions LICENSE.3RDPARTY
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

[lib/external/idtree.c]
/*
* Copyright (C) 2015-2020 Leah Neukirchen
* Parts of code derived from musl libc, which is
* Copyright (C) 2005-2014 Rich Felker, et al.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
90 changes: 86 additions & 4 deletions bin/xbps-create/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member Author

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?


#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
Expand All @@ -41,6 +44,7 @@
#include <libgen.h>
#include <locale.h>
#include <dirent.h>
#include <fnmatch.h>

#include <xbps.h>
#include "queue.h"
Expand All @@ -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 =
Expand Down Expand Up @@ -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"
Copy link
Member Author

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something else to consider: should chown -R be representable?

" 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"
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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' },
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -965,6 +1043,9 @@ main(int argc, char **argv)
case '5':
sourcepkg = optarg;
break;
case '6':
chownlst = optarg;
break;
case '?':
default:
usage(true);
Expand Down Expand Up @@ -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)
Expand Down
16 changes: 16 additions & 0 deletions bin/xbps-create/xbps-create.1
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ is a relative path, the symlink will be created relative to
.Em target .
.It Fl -build-options Ar string
A string containing the build options used in package.
.It Fl -chown Ar list
Set the ownership of package files and directories.
This expects a whitespace-separated list of
.Ar <pattern>:<user>:<group> ,
where
.Ar <pattern>
is an
.Xr fnmatch 3
pattern.
If
.Ar <user>
or
.Ar <group>
are empty, root is assumed.
Example:
.Ar '/usr/lib/foo/*:foo:foo /usr/bin/foo::foo'
.It Fl -compression Ar none | gzip | bzip2 | xz | lz4 | zstd
Set the binary package compression format. If unset, defaults to
.Ar zstd .
Expand Down
1 change: 1 addition & 0 deletions bin/xbps-pkgdb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ BIN = xbps-pkgdb
OBJS = main.o check.o check_pkg_files.o
OBJS += check_pkg_alternatives.o check_pkg_rundeps.o
OBJS += check_pkg_symlinks.o check_pkg_unneeded.o
OBJS += check_files.o

include $(TOPDIR)/mk/prog.mk
52 changes: 52 additions & 0 deletions bin/xbps-pkgdb/check_files.c
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;
}
Loading