diff --git a/bin/xbps-query/defs.h b/bin/xbps-query/defs.h
index 2a174725..ab5bd397 100644
--- a/bin/xbps-query/defs.h
+++ b/bin/xbps-query/defs.h
@@ -39,9 +39,9 @@ void show_pkg_info(xbps_dictionary_t);
void show_pkg_info_one(xbps_dictionary_t, const char *);
int show_pkg_info_from_metadir(struct xbps_handle *, const char *,
const char *);
-int show_pkg_files(xbps_dictionary_t);
-int show_pkg_files_from_metadir(struct xbps_handle *, const char *);
-int repo_show_pkg_files(struct xbps_handle *, const char *);
+int show_pkg_files(xbps_dictionary_t, bool);
+int show_pkg_files_from_metadir(struct xbps_handle *, const char *, bool);
+int repo_show_pkg_files(struct xbps_handle *, const char *, bool);
int cat_file(struct xbps_handle *, const char *, const char *);
int repo_cat_file(struct xbps_handle *, const char *, const char *);
int repo_show_pkg_info(struct xbps_handle *, const char *, const char *);
diff --git a/bin/xbps-query/main.c b/bin/xbps-query/main.c
index 44316c1a..992b591e 100644
--- a/bin/xbps-query/main.c
+++ b/bin/xbps-query/main.c
@@ -53,6 +53,7 @@ usage(bool fail)
" specified multiple times\n"
" --regex Use Extended Regular Expressions to match\n"
" --fulldeptree Full dependency tree for -x/--deps\n"
+ " --long Show permissions, ownership, and size for -f/--files\n"
" -r, --rootdir
Full path to rootdir\n"
" -V, --version Show XBPS version\n"
" -v, --verbose Verbose messages\n"
@@ -100,6 +101,7 @@ main(int argc, char **argv)
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ "files", required_argument, NULL, 'f' },
+ { "long", no_argument, NULL, 4 },
{ "deps", required_argument, NULL, 'x' },
{ "revdeps", required_argument, NULL, 'X' },
{ "regex", no_argument, NULL, 0 },
@@ -112,14 +114,14 @@ main(int argc, char **argv)
int c, flags, rv;
bool list_pkgs, list_repos, orphans, own, list_repolock;
bool list_manual, list_hold, show_prop, show_files, show_deps, show_rdeps;
- bool show, pkg_search, regex, repo_mode, opmode, fulldeptree;
+ bool show, pkg_search, regex, repo_mode, opmode, fulldeptree, long_listing;
rootdir = cachedir = confdir = props = pkg = catfile = NULL;
flags = rv = c = 0;
list_pkgs = list_repos = list_hold = orphans = pkg_search = own = false;
list_manual = list_repolock = show_prop = show_files = false;
regex = show = show_deps = show_rdeps = fulldeptree = false;
- repo_mode = opmode = false;
+ repo_mode = opmode = long_listing = false;
memset(&xh, 0, sizeof(xh));
@@ -213,6 +215,9 @@ main(int argc, char **argv)
case 3:
list_repolock = opmode = true;
break;
+ case 4:
+ long_listing = true;
+ break;
case '?':
default:
usage(true);
@@ -302,9 +307,9 @@ main(int argc, char **argv)
} else if (show_files) {
/* show-files mode */
if (repo_mode)
- rv = repo_show_pkg_files(&xh, pkg);
+ rv = repo_show_pkg_files(&xh, pkg, long_listing);
else
- rv = show_pkg_files_from_metadir(&xh, pkg);
+ rv = show_pkg_files_from_metadir(&xh, pkg, long_listing);
} else if (show_deps) {
/* show-deps mode */
diff --git a/bin/xbps-query/show-info-files.c b/bin/xbps-query/show-info-files.c
index d9fa5174..2021fb9b 100644
--- a/bin/xbps-query/show-info-files.c
+++ b/bin/xbps-query/show-info-files.c
@@ -32,6 +32,8 @@
#include
#include
#include
+#include
+#include
#include
#include "defs.h"
@@ -39,6 +41,60 @@
#define _BOLD "\033[1m"
#define _RESET "\033[m"
+/*
+1111 111 111 111 111
+^~~~ ^~~ ^~~ ^~~ ^~~
+ | | | | `- other rwx
+ | | | `- group rwx
+ | | `- user rwx
+ | `- suid, sgid, sticky
+ `- file type
+*/
+static void
+print_mode(const mode_t mode) {
+ char hmode[10] = "";
+ switch (mode & S_IFMT) {
+ case S_IFREG: hmode[0] = '-'; break;
+ case S_IFLNK: hmode[0] = 'l'; break;
+ case S_IFDIR: hmode[0] = 'd'; break;
+ default: hmode[0] = '?'; break;
+ }
+ hmode[1] = (mode & S_IRUSR) ? 'r' : '-';
+ hmode[2] = (mode & S_IWUSR) ? 'w' : '-';
+ if ((mode & S_ISUID) && (mode & S_IXUSR)) {
+ hmode[3] = 's';
+ } else if (mode & S_ISUID) {
+ hmode[3] = 'S';
+ } else if (mode & S_IXUSR) {
+ hmode[3] = 'x';
+ } else {
+ hmode[3] = '-';
+ }
+ hmode[4] = (mode & S_IRGRP) ? 'r' : '-';
+ hmode[5] = (mode & S_IWGRP) ? 'w' : '-';
+ if ((mode & S_ISGID) && (mode & S_IXGRP)) {
+ hmode[6] = 's';
+ } else if (mode & S_ISGID) {
+ hmode[6] = 'S';
+ } else if (mode & S_IXGRP) {
+ hmode[6] = 'x';
+ } else {
+ hmode[6] = '-';
+ }
+ hmode[7] = (mode & S_IROTH) ? 'r' : '-';
+ hmode[8] = (mode & S_IWOTH) ? 'w' : '-';
+ if ((mode & S_ISVTX) && (mode & S_IXOTH)) {
+ hmode[9] = 't';
+ } else if (mode & S_ISVTX) {
+ hmode[9] = 'T';
+ } else if (mode & S_IXOTH) {
+ hmode[9] = 'x';
+ } else {
+ hmode[9] = '-';
+ }
+ printf("%s\t", hmode);
+}
+
static void
print_value_obj(const char *keyname, xbps_object_t obj,
const char *indent, const char *bold,
@@ -187,11 +243,17 @@ show_pkg_info(xbps_dictionary_t dict)
}
int
-show_pkg_files(xbps_dictionary_t filesd)
+show_pkg_files(xbps_dictionary_t filesd, bool long_listing)
{
xbps_array_t array, allkeys;
xbps_object_t obj;
xbps_dictionary_keysym_t ksym;
+ uint64_t size;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ struct passwd *user;
+ struct group *grp;
const char *keyname = NULL, *file = NULL;
if (xbps_object_type(filesd) != XBPS_TYPE_DICTIONARY)
@@ -214,6 +276,31 @@ show_pkg_files(xbps_dictionary_t filesd)
obj = xbps_array_get(array, x);
if (xbps_object_type(obj) != XBPS_TYPE_DICTIONARY)
continue;
+ if (long_listing) {
+ mode = uid = gid = size = 0;
+ if (xbps_dictionary_get_uint32(obj, "mode", &mode)) {
+ print_mode(mode);
+ } else {
+ printf("?\t");
+ }
+ if (xbps_dictionary_get_uint32(obj, "uid", &uid)) {
+ user = getpwuid(uid);
+ (user != NULL) ? printf("%s\t", user->pw_name) : printf("%u\t", uid);
+ } else {
+ printf("?\t");
+ }
+ if (xbps_dictionary_get_uint32(obj, "gid", &gid)) {
+ grp = getgrgid(gid);
+ (grp != NULL) ? printf("%s\t", grp->gr_name) : printf("%u\t", gid);
+ } else {
+ printf("?\t");
+ }
+ if (xbps_dictionary_get_uint64(obj, "size", &size)) {
+ printf("%lu\t", size);
+ } else {
+ printf("?\t");
+ }
+ }
xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
printf("%s", file);
if (xbps_dictionary_get_cstring_nocopy(obj,
@@ -248,7 +335,7 @@ show_pkg_info_from_metadir(struct xbps_handle *xhp,
}
int
-show_pkg_files_from_metadir(struct xbps_handle *xhp, const char *pkg)
+show_pkg_files_from_metadir(struct xbps_handle *xhp, const char *pkg, bool long_listing)
{
xbps_dictionary_t d;
int rv = 0;
@@ -257,7 +344,7 @@ show_pkg_files_from_metadir(struct xbps_handle *xhp, const char *pkg)
if (d == NULL)
return ENOENT;
- rv = show_pkg_files(d);
+ rv = show_pkg_files(d, long_listing);
return rv;
}
@@ -324,7 +411,7 @@ repo_cat_file(struct xbps_handle *xhp, const char *pkg, const char *file)
}
int
-repo_show_pkg_files(struct xbps_handle *xhp, const char *pkg)
+repo_show_pkg_files(struct xbps_handle *xhp, const char *pkg, bool long_listing)
{
xbps_dictionary_t pkgd;
int rv;
@@ -337,7 +424,7 @@ repo_show_pkg_files(struct xbps_handle *xhp, const char *pkg)
return errno;
}
- rv = show_pkg_files(pkgd);
+ rv = show_pkg_files(pkgd, long_listing);
xbps_object_release(pkgd);
return rv;
}
diff --git a/bin/xbps-query/xbps-query.1 b/bin/xbps-query/xbps-query.1
index b4c36418..0673fbe0 100644
--- a/bin/xbps-query/xbps-query.1
+++ b/bin/xbps-query/xbps-query.1
@@ -129,6 +129,10 @@ modes.
Prints a full dependency tree in the
.Sy show dependencies
mode.
+.It Fl -long
+Prints permissions, ownership, and filesize in the
+.Sy files
+mode.
.It Fl r, Fl -rootdir Ar dir
Specifies a full path for the target root directory.
.It Fl v, Fl -verbose
diff --git a/data/_xbps b/data/_xbps
index 31587571..2514215c 100644
--- a/data/_xbps
+++ b/data/_xbps
@@ -154,6 +154,7 @@ _xbps_query() {
{-p,--property=-}'[Show properties]:property:($_xbps_properties)' \
--regex'[Use Extended Regular Expressions to match]' \
--fulldeptree'[Full dependency tree for -x/--deps]' \
+ --long'[Show permissions, ownership, and size for -f/--files]' \
{-R,--repository}'[Enable repository mode]' \
'*'--repository=-'[Add repository to the top of the list]:repository url:_files -/' \
- '(mode)' \