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>
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"
@@ -66,6 +70,7 @@ struct xentry {
6670 char * file , * target ;
6771 char sha256 [XBPS_SHA256_SIZE ];
6872 ino_t inode ;
73+ mode_t mode ;
6974};
7075
7176static 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
249314static void
250315process_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,8 @@ 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 -> mode )
722+ xbps_dictionary_set_uint32 (d , "mode" , xe -> mode );
653723
654724 xbps_array_add (a , d );
655725 xbps_object_release (d );
@@ -832,6 +902,7 @@ main(int argc, char **argv)
832902 { "build-options" , required_argument , NULL , '2' },
833903 { "built-with" , required_argument , NULL , 'B' },
834904 { "changelog" , required_argument , NULL , 'c' },
905+ { "chown" , required_argument , NULL , '6' },
835906 { "compression" , required_argument , NULL , '3' },
836907 { "config-files" , required_argument , NULL , 'F' },
837908 { "conflicts" , required_argument , NULL , 'C' },
@@ -865,7 +936,7 @@ main(int argc, char **argv)
865936 const char * provides , * pkgver , * replaces , * reverts , * desc , * ldesc ;
866937 const char * arch , * config_files , * mutable_files , * version , * changelog ;
867938 const char * buildopts , * shlib_provides , * shlib_requires , * alternatives ;
868- const char * compression , * tags = NULL , * srcrevs = NULL , * sourcepkg = NULL ;
939+ const char * compression , * tags = NULL , * srcrevs = NULL , * sourcepkg = NULL , * chownlst ;
869940 char pkgname [XBPS_NAME_SIZE ], * binpkg , * tname , * p , cwd [PATH_MAX - 1 ];
870941 bool quiet = false, preserve = false;
871942 int c , pkg_fd ;
@@ -874,7 +945,7 @@ main(int argc, char **argv)
874945 arch = conflicts = deps = homepage = license = maint = compression = NULL ;
875946 provides = pkgver = replaces = reverts = desc = ldesc = bwith = NULL ;
876947 buildopts = config_files = mutable_files = shlib_provides = NULL ;
877- alternatives = shlib_requires = changelog = NULL ;
948+ alternatives = shlib_requires = changelog = chownlst = NULL ;
878949
879950 while ((c = getopt_long (argc , argv , shortopts , longopts , NULL )) != -1 ) {
880951 if (optarg && strcmp (optarg , "" ) == 0 )
@@ -965,6 +1036,9 @@ main(int argc, char **argv)
9651036 case '5' :
9661037 sourcepkg = optarg ;
9671038 break ;
1039+ case '6' :
1040+ chownlst = optarg ;
1041+ break ;
9681042 case '?' :
9691043 default :
9701044 usage (true);
@@ -1081,6 +1155,7 @@ main(int argc, char **argv)
10811155 die ("xbps_dictionary_create" );
10821156
10831157 process_destdir (mutable_files );
1158+ process_chown_patterns (chownlst );
10841159
10851160 /* Back to original cwd after file tree walk processing */
10861161 if (chdir (p ) == -1 )
0 commit comments