Skip to content

Commit 3678e29

Browse files
committed
bin/xbps-create: record file mode, owner, and group
1 parent 33c01e6 commit 3678e29

1 file changed

Lines changed: 83 additions & 4 deletions

File tree

bin/xbps-create/main.c

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2323
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424
*/
25+
26+
#define _DEFAULT_SOURCE
27+
2528
#include <sys/types.h>
2629
#include <sys/param.h>
2730
#include <sys/stat.h>
@@ -41,6 +44,7 @@
4144
#include <libgen.h>
4245
#include <locale.h>
4346
#include <dirent.h>
47+
#include <fnmatch.h>
4448

4549
#include <xbps.h>
4650
#include "queue.h"
@@ -63,9 +67,10 @@ struct xentry {
6367
TAILQ_ENTRY(xentry) entries;
6468
uint64_t size;
6569
enum entry_type type;
66-
char *file, *target;
70+
char *file, *target, *user, *group;
6771
char sha256[XBPS_SHA256_SIZE];
6872
ino_t inode;
73+
mode_t mode;
6974
};
7075

7176
static TAILQ_HEAD(xentry_head, xentry) xentry_list =
@@ -109,6 +114,9 @@ usage(bool fail)
109114
" 'vi:/usr/bin/vi:/usr/bin/vim foo:/usr/bin/foo:/usr/bin/blah'\n"
110115
" --build-options A string with the used build options\n"
111116
" --compression Compression format: none, gzip, bzip2, lz4, xz, zstd (default)\n"
117+
" --chown Set the ownership of files and directories.\n"
118+
" This expects a blank-separated list of <pattern>:<user>:<group>,\n"
119+
" where '<pattern>' is an fnmatch(3) pattern.\n"
112120
" --shlib-provides List of provided shared libraries (blank separated list,\n"
113121
" e.g 'libfoo.so.1 libblah.so.2')\n"
114122
" --shlib-requires List of required shared libraries (blank separated list,\n"
@@ -245,6 +253,63 @@ process_one_alternative(const char *altgrname, const char *val)
245253
}
246254
}
247255

256+
static void
257+
process_chown_pattern(const char *key, const char *fpat, const char *user, const char *group) {
258+
xbps_object_iterator_t iter;
259+
xbps_object_t obj;
260+
const char *fname;
261+
262+
if ((iter = xbps_array_iter_from_dict(pkg_filesd, key)) != NULL) {
263+
while ((obj = xbps_object_iterator_next(iter))) {
264+
xbps_dictionary_get_cstring_nocopy(obj, "file", &fname);
265+
if (fnmatch(fpat, fname, 0) == 0) {
266+
if (user != NULL)
267+
xbps_dictionary_set_cstring(obj, "user", user);
268+
if (group != NULL)
269+
xbps_dictionary_set_cstring(obj, "group", group);
270+
}
271+
}
272+
}
273+
}
274+
275+
static void
276+
process_chown_patterns(const char *val) {
277+
char *raw, *itm, *fpat, *user, *group;
278+
279+
if (val == NULL)
280+
return;
281+
282+
raw = strdup(val);
283+
284+
while ((itm = strsep(&raw, " "))) {
285+
fpat = strsep(&itm, ":");
286+
if (fpat == NULL) {
287+
xbps_warn_printf("%s: skipping chown pattern '%s': empty pattern", _PROGNAME, val);
288+
continue;
289+
}
290+
291+
user = strsep(&itm, ":");
292+
if (strcmp(user, "root") == 0)
293+
user = NULL;
294+
group = strsep(&itm, ":");
295+
if (strcmp(group, "root") == 0)
296+
group = NULL;
297+
298+
if (itm != NULL)
299+
xbps_warn_printf("%s: chown pattern '%s' contains extra data: %s", _PROGNAME, val, itm);
300+
301+
if (user == NULL && group == NULL) {
302+
xbps_warn_printf("%s: skipping chown pattern '%s': user and group empty or root", _PROGNAME, val);
303+
continue;
304+
}
305+
306+
process_chown_pattern("dirs", fpat, user, group);
307+
process_chown_pattern("files", fpat, user, group);
308+
process_chown_pattern("links", fpat, user, group);
309+
}
310+
311+
free(raw);
312+
}
248313

249314
static void
250315
process_dict_of_arrays(const char *key UNUSED, const char *val)
@@ -396,6 +461,10 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED
396461
goto out;
397462
}
398463

464+
// symlinks don't have a mode on linux
465+
if (!S_ISLNK(sb->st_mode))
466+
xe->mode = sb->st_mode;
467+
399468
if (S_ISLNK(sb->st_mode)) {
400469
char buf[PATH_MAX];
401470
ssize_t len;
@@ -530,7 +599,6 @@ ftw_cb(const char *fpath, const struct stat *sb, const struct dirent *dir UNUSED
530599
xbps_dictionary_set_uint64(fileinfo, "inode", sb->st_ino);
531600
xe->inode = sb->st_ino;
532601
xe->size = (uint64_t)sb->st_size;
533-
534602
} else if (S_ISDIR(sb->st_mode)) {
535603
/* directory */
536604
xbps_dictionary_set_cstring_nocopy(fileinfo, "type", "dirs");
@@ -650,6 +718,12 @@ process_xentry(enum entry_type type, const char *mutable_files)
650718
xbps_dictionary_set_cstring(d, "sha256", xe->sha256);
651719
if (xe->size)
652720
xbps_dictionary_set_uint64(d, "size", xe->size);
721+
if (xe->user)
722+
xbps_dictionary_set_cstring(d, "user", xe->user);
723+
if (xe->group)
724+
xbps_dictionary_set_cstring(d, "group", xe->group);
725+
if (xe->mode)
726+
xbps_dictionary_set_uint32(d, "mode", xe->mode);
653727

654728
xbps_array_add(a, d);
655729
xbps_object_release(d);
@@ -832,6 +906,7 @@ main(int argc, char **argv)
832906
{ "build-options", required_argument, NULL, '2' },
833907
{ "built-with", required_argument, NULL, 'B' },
834908
{ "changelog", required_argument, NULL, 'c'},
909+
{ "chown", required_argument, NULL, '6'},
835910
{ "compression", required_argument, NULL, '3' },
836911
{ "config-files", required_argument, NULL, 'F' },
837912
{ "conflicts", required_argument, NULL, 'C' },
@@ -865,7 +940,7 @@ main(int argc, char **argv)
865940
const char *provides, *pkgver, *replaces, *reverts, *desc, *ldesc;
866941
const char *arch, *config_files, *mutable_files, *version, *changelog;
867942
const char *buildopts, *shlib_provides, *shlib_requires, *alternatives;
868-
const char *compression, *tags = NULL, *srcrevs = NULL, *sourcepkg = NULL;
943+
const char *compression, *tags = NULL, *srcrevs = NULL, *sourcepkg = NULL, *chownlst;
869944
char pkgname[XBPS_NAME_SIZE], *binpkg, *tname, *p, cwd[PATH_MAX-1];
870945
bool quiet = false, preserve = false;
871946
int c, pkg_fd;
@@ -874,7 +949,7 @@ main(int argc, char **argv)
874949
arch = conflicts = deps = homepage = license = maint = compression = NULL;
875950
provides = pkgver = replaces = reverts = desc = ldesc = bwith = NULL;
876951
buildopts = config_files = mutable_files = shlib_provides = NULL;
877-
alternatives = shlib_requires = changelog = NULL;
952+
alternatives = shlib_requires = changelog = chownlst = NULL;
878953

879954
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
880955
if (optarg && strcmp(optarg, "") == 0)
@@ -965,6 +1040,9 @@ main(int argc, char **argv)
9651040
case '5':
9661041
sourcepkg = optarg;
9671042
break;
1043+
case '6':
1044+
chownlst = optarg;
1045+
break;
9681046
case '?':
9691047
default:
9701048
usage(true);
@@ -1081,6 +1159,7 @@ main(int argc, char **argv)
10811159
die("xbps_dictionary_create");
10821160

10831161
process_destdir(mutable_files);
1162+
process_chown_patterns(chownlst);
10841163

10851164
/* Back to original cwd after file tree walk processing */
10861165
if (chdir(p) == -1)

0 commit comments

Comments
 (0)