[pacman-dev] [PATCH v2] pacman+libalpm: print version names for conflicting packages

2019-11-27 Thread morganamilo
When ever pacman prints a conflict, it now prints pkgname-version,
instead of just pkgname.

alpm_conflict_t now carries pointers to alpm_pkg_t instead of just the
names of each package.

Fixes FS#12536 (point 2)

---

v2: dupe each alpm_pkg_t

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 956284bd..b0aa0671 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -247,10 +247,8 @@ typedef struct _alpm_depmissing_t {
 
 /** Conflict */
 typedef struct _alpm_conflict_t {
-   unsigned long package1_hash;
-   unsigned long package2_hash;
-   char *package1;
-   char *package2;
+   alpm_pkg_t *package1;
+   alpm_pkg_t *package2;
alpm_depend_t *reason;
 } alpm_conflict_t;
 
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 80827ed6..08ae86cb 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -49,11 +49,8 @@ static alpm_conflict_t *conflict_new(alpm_pkg_t *pkg1, 
alpm_pkg_t *pkg2,
alpm_conflict_t *conflict;
 
CALLOC(conflict, 1, sizeof(alpm_conflict_t), return NULL);
-
-   conflict->package1_hash = pkg1->name_hash;
-   conflict->package2_hash = pkg2->name_hash;
-   STRDUP(conflict->package1, pkg1->name, goto error);
-   STRDUP(conflict->package2, pkg2->name, goto error);
+   ASSERT(_alpm_pkg_dup(pkg1, >package1) == 0, goto error);
+   ASSERT(_alpm_pkg_dup(pkg2, >package2) == 0, goto error);
conflict->reason = reason;
 
return conflict;
@@ -69,8 +66,8 @@ error:
 void SYMEXPORT alpm_conflict_free(alpm_conflict_t *conflict)
 {
ASSERT(conflict != NULL, return);
-   FREE(conflict->package2);
-   FREE(conflict->package1);
+   _alpm_pkg_free(conflict->package1);
+   _alpm_pkg_free(conflict->package2);
FREE(conflict);
 }
 
@@ -79,20 +76,7 @@ void SYMEXPORT alpm_conflict_free(alpm_conflict_t *conflict)
  */
 alpm_conflict_t *_alpm_conflict_dup(const alpm_conflict_t *conflict)
 {
-   alpm_conflict_t *newconflict;
-   CALLOC(newconflict, 1, sizeof(alpm_conflict_t), return NULL);
-
-   newconflict->package1_hash = conflict->package1_hash;
-   newconflict->package2_hash = conflict->package2_hash;
-   STRDUP(newconflict->package1, conflict->package1, goto error);
-   STRDUP(newconflict->package2, conflict->package2, goto error);
-   newconflict->reason = conflict->reason;
-
-   return newconflict;
-
-error:
-   alpm_conflict_free(newconflict);
-   return NULL;
+   return conflict_new(conflict->package1, conflict->package2, 
conflict->reason);
 }
 
 /**
@@ -108,10 +92,10 @@ static int conflict_isin(alpm_conflict_t *needle, 
alpm_list_t *haystack)
alpm_list_t *i;
for(i = haystack; i; i = i->next) {
alpm_conflict_t *conflict = i->data;
-   if(needle->package1_hash == conflict->package1_hash
-   && needle->package2_hash == 
conflict->package2_hash
-   && strcmp(needle->package1, conflict->package1) 
== 0
-   && strcmp(needle->package2, conflict->package2) 
== 0) {
+   if(needle->package1->name_hash == conflict->package2->name_hash
+   && needle->package2->name_hash == 
conflict->package2->name_hash
+   && strcmp(needle->package1->name, 
conflict->package1->name) == 0
+   && strcmp(needle->package2->name, 
conflict->package2->name) == 0) {
return 1;
}
}
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 97a351fe..d26a1323 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -510,21 +510,23 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t 
**data)
 
for(i = deps; i; i = i->next) {
alpm_conflict_t *conflict = i->data;
+   const char *name1 = conflict->package1->name;
+   const char *name2 = conflict->package2->name;
alpm_pkg_t *rsync, *sync, *sync1, *sync2;
 
/* have we already removed one of the conflicting 
targets? */
-   sync1 = alpm_pkg_find(trans->add, conflict->package1);
-   sync2 = alpm_pkg_find(trans->add, conflict->package2);
+   sync1 = alpm_pkg_find(trans->add, name1);
+   sync2 = alpm_pkg_find(trans->add, name2);
if(!sync1 || !sync2) {
continue;
}
 
_alpm_log(handle, ALPM_LOG_DEBUG, "conflicting packages 
in the sync list: '%s' <-> '%s'\n",
-   conflict->package1, conflict->package2);
+   name1, name2);
 
/* if sync1 provides sync2, we remove sync2 from the 
targets, and vice versa */
-   

[pacman-dev] [PATCH 2/2] remove: Don't follow symlinks in checking if a file can be removed

2019-11-27 Thread Ryan Gonzalez
Otherwise, symlinks to non-removable files will be logged as unable to
be removed.

Signed-off-by: Ryan Gonzalez 
---
 lib/libalpm/remove.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 9030bfee..bb980e7d 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -339,7 +339,7 @@ static int can_remove_file(alpm_handle_t *handle, const 
alpm_file_t *file)
 
/* If we fail write permissions due to a read-only filesystem, abort.
 * Assume all other possible failures are covered somewhere else */
-   if(_alpm_access(handle, NULL, filepath, W_OK) == -1) {
+   if(_alpm_access_flags(handle, NULL, filepath, W_OK, 
AT_SYMLINK_NOFOLLOW) == -1) {
if(errno != EACCES && errno != ETXTBSY && access(filepath, 
F_OK) == 0) {
/* only return failure if the file ACTUALLY exists and 
we can't write to
 * it - ignore "chmod -w" simple permission failures */
-- 
2.23.0


[pacman-dev] [PATCH 1/2] util: Add _alpm_access_flags

2019-11-27 Thread Ryan Gonzalez
This changes _alpm_access* to use faccessat,

which allows behavior flags to be passed.

Signed-off-by: Ryan Gonzalez 
---
 lib/libalpm/util.c | 18 --
 lib/libalpm/util.h |  2 ++
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index a4d62c7c..8d653b16 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -1333,16 +1333,22 @@ alpm_time_t _alpm_parsedate(const char *line)
return (alpm_time_t)result;
 }
 
-/** Wrapper around access() which takes a dir and file argument
+int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int 
amode) {
+   return _alpm_access_flags(handle, dir, file, amode, 0);
+}
+
+/** Wrapper around faccessat() which takes a dir and file argument
  * separately and generates an appropriate error message.
  * If dir is NULL file will be treated as the whole path.
  * @param handle an alpm handle
  * @param dir directory path ending with and slash
  * @param file filename
- * @param amode access mode as described in access()
- * @return int value returned by access()
+ * @param amode access mode as described in faccessat()
+ * @param flags flags to pass as described in faccessat()
+ * @return int value returned by faccessat()
  */
-int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int 
amode)
+int _alpm_access_flags(alpm_handle_t *handle, const char *dir, const char 
*file, int amode,
+   int flags)
 {
size_t len = 0;
int ret = 0;
@@ -1354,11 +1360,11 @@ int _alpm_access(alpm_handle_t *handle, const char 
*dir, const char *file, int a
CALLOC(check_path, len, sizeof(char), RET_ERR(handle, 
ALPM_ERR_MEMORY, -1));
snprintf(check_path, len, "%s%s", dir, file);
 
-   ret = access(check_path, amode);
+   ret = faccessat(AT_FDCWD, check_path, amode, flags);
free(check_path);
} else {
dir = "";
-   ret = access(file, amode);
+   ret = faccessat(AT_FDCWD, file, amode, flags);
}
 
if(ret != 0) {
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 71dadc2c..1af79571 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -143,6 +143,8 @@ alpm_time_t _alpm_parsedate(const char *line);
 int _alpm_raw_cmp(const char *first, const char *second);
 int _alpm_raw_ncmp(const char *first, const char *second, size_t max);
 int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int 
amode);
+int _alpm_access_flags(alpm_handle_t *handle, const char *dir, const char 
*file, int amode,
+   int flags);
 int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string);
 int _alpm_fnmatch(const void *pattern, const void *string);
 void *_alpm_realloc(void **data, size_t *current, const size_t required);
-- 
2.23.0


Re: [pacman-dev] [PATCH 2/3] libmakepkg: use readelf instead of file for finding ELF file types

2019-11-27 Thread Eli Schwartz
On 11/27/19 12:32 PM, Ethan Sommer wrote:
>>> --- a/scripts/libmakepkg/tidy/strip.sh.in
>>> +++ b/scripts/libmakepkg/tidy/strip.sh.in
>>> @@ -111,22 +111,20 @@ tidy_strip() {
>>>
>>>   local binary strip_flags
>>>   find . -type f -perm -u+w -print0 2>/dev/null | while IFS= 
>>> read -rd '' binary ; do
>>> - case "$(file -bi "$binary")" in
>>> - *application/x-sharedlib*)  # Libraries (.so)
>>> + case "$(LC_ALL=C readelf -h "$binary" 2>/dev/null)" in
>>
>> More squelching of errors.
> The error redirection to null is because readelf outputs an error when
> the file it is run on isn't an ELF file at all, and obviously that error
> is unwanted.

Right, we just want all the other errors.

>> Incidentally, is the output of this, documented, or can it arbitrarily
>> change in the future? file is guaranteed to emit output in the
>> RFC-documented IANA media type format.
> These file types and their specification in the file header are part of
> the ELF spec

Let's pretend I stated from the beginning that I trust the readelf
program to be able to also interpret future revisions of the file format.

> , and the readelf output has remained consistent, at least
> the part that matters to us, and the relevant part is the same across 4
> different implementations, and I doubt there will be some change of the
> word 'Type:' being used, given that the ELF specification refers to those
> file types as 'types'.

I'll take that as a "no, but it's worked for long enough they probably
won't change it now". Which I suppose is not so unreasonable...

-- 
Eli Schwartz
Bug Wrangler and Trusted User



signature.asc
Description: OpenPGP digital signature


[pacman-dev] [PATCH v2] pacman: print error when -Fx is given invalid regex

2019-11-27 Thread morganamilo
When processing the targets for -Fx, compile all the regex ahead of
time, printing an error for each that failed to compile. Then, if they all
compiled successfully, continue with printing files.

Signed-off-by: morganamilo 

---

v2:
Add comment about why we don't free targ
Fix whitespace error

I have vim set to display trialing whitespace so normally I catch it.
Not sure why I didn't this time.

Also I agree that running all the regex against each target before
moving on to the next is a good improvement. This patch is already kinda
long though, so I'll do it another time.

diff --git a/src/pacman/files.c b/src/pacman/files.c
index 3b6dc23b..6fcc6e9b 100644
--- a/src/pacman/files.c
+++ b/src/pacman/files.c
@@ -94,17 +94,27 @@ static void print_match(alpm_list_t *match, alpm_db_t 
*repo, alpm_pkg_t *pkg, in
}
 }
 
+struct filetarget {
+   char *targ;
+   int exact_file;
+   regex_t reg;
+};
+
+static void filetarget_free(struct filetarget *ftarg) {
+   regfree(>reg);
+   /* we don't own ftarg->targ so don't free it */
+   free(ftarg);
+}
+
 static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) {
int ret = 0;
-   alpm_list_t *t;
+   alpm_list_t *t, *filetargs = NULL;
 
for(t = targets; t; t = alpm_list_next(t)) {
char *targ = t->data;
-   alpm_list_t *s;
-   int found = 0;
-   regex_t reg;
size_t len = strlen(targ);
int exact_file = strchr(targ, '/') != NULL;
+   regex_t reg;
 
if(exact_file) {
while(len > 1 && targ[0] == '/') {
@@ -115,11 +125,33 @@ static int files_search(alpm_list_t *syncs, alpm_list_t 
*targets, int regex) {
 
if(regex) {
if(regcomp(, targ, REG_EXTENDED | REG_NOSUB | 
REG_ICASE | REG_NEWLINE) != 0) {
-   /* TODO: error message */
-   goto notfound;
+   pm_printf(ALPM_LOG_ERROR,
+   _("invalid regular expression 
'%s'\n"), targ);
+   ret = 1;
+   continue;
}
}
 
+   struct filetarget *ftarg = malloc(sizeof(struct filetarget));
+   ftarg->targ = targ;
+   ftarg->exact_file = exact_file;
+   ftarg->reg = reg;
+
+   filetargs = alpm_list_add(filetargs, ftarg);
+   }
+
+   if(ret != 0) {
+   goto cleanup;
+   }
+
+   for(t = filetargs; t; t = alpm_list_next(t)) {
+   struct filetarget *ftarg = t->data;
+   char *targ = ftarg->targ;
+   regex_t *reg = >reg;
+   int exact_file = ftarg->exact_file;
+   alpm_list_t *s;
+   int found = 0;
+
for(s = syncs; s; s = alpm_list_next(s)) {
alpm_list_t *p;
alpm_db_t *repo = s->data;
@@ -135,7 +167,7 @@ static int files_search(alpm_list_t *syncs, alpm_list_t 
*targets, int regex) {
if (regex) {
for(size_t f = 0; f < 
files->count; f++) {
char *c = 
files->files[f].name;
-   if(regexec(, c, 0, 
0, 0) == 0) {
+   if(regexec(reg, c, 0, 
0, 0) == 0) {
match = 
alpm_list_add(match, files->files[f].name);
found = 1;
}
@@ -151,7 +183,7 @@ static int files_search(alpm_list_t *syncs, alpm_list_t 
*targets, int regex) {
char *c = 
strrchr(files->files[f].name, '/');
if(c && *(c + 1)) {
if(regex) {
-   m = 
regexec(, (c + 1), 0, 0, 0);
+   m = 
regexec(reg, (c + 1), 0, 0, 0);
} else {
m = strcmp(c + 
1, targ);
}
@@ -170,16 +202,15 @@ static int files_search(alpm_list_t *syncs, alpm_list_t 
*targets, int regex) {
}
}
 
-   if(regex) {
-   regfree();
-   }
-
-notfound:
if(!found) {
ret = 1;
}
}
 

Re: [pacman-dev] [PATCH 2/3] libmakepkg: use readelf instead of file for finding ELF file types

2019-11-27 Thread Ethan Sommer
> > --- a/scripts/libmakepkg/tidy/strip.sh.in
> > +++ b/scripts/libmakepkg/tidy/strip.sh.in
> > @@ -111,22 +111,20 @@ tidy_strip() {
> >
> >   local binary strip_flags
> >   find . -type f -perm -u+w -print0 2>/dev/null | while IFS= 
> > read -rd '' binary ; do
> > - case "$(file -bi "$binary")" in
> > - *application/x-sharedlib*)  # Libraries (.so)
> > + case "$(LC_ALL=C readelf -h "$binary" 2>/dev/null)" in
>
> More squelching of errors.
The error redirection to null is because readelf outputs an error when
the file it is run on isn't an ELF file at all, and obviously that error
is unwanted.

> Incidentally, is the output of this, documented, or can it arbitrarily
> change in the future? file is guaranteed to emit output in the
> RFC-documented IANA media type format.
These file types and their specification in the file header are part of
the ELF spec, and the readelf output has remained consistent, at least
the part that matters to us, and the relevant part is the same across 4
different implementations, and I doubt there will be some change of the
word 'Type:' being used, given that the ELF specification refers to those
file types as 'types'.


Re: [pacman-dev] [PATCH 2/3] libmakepkg: use readelf instead of file for finding ELF file types

2019-11-27 Thread Eli Schwartz
On 11/26/19 4:29 PM, Ethan Sommer wrote:
> Signed-off-by: Ethan Sommer 
> ---
>  scripts/libmakepkg/tidy/strip.sh.in | 26 --
>  1 file changed, 12 insertions(+), 14 deletions(-)
> 
> diff --git a/scripts/libmakepkg/tidy/strip.sh.in 
> b/scripts/libmakepkg/tidy/strip.sh.in
> index 1bd810f0..301d1989 100644
> --- a/scripts/libmakepkg/tidy/strip.sh.in
> +++ b/scripts/libmakepkg/tidy/strip.sh.in
> @@ -111,22 +111,20 @@ tidy_strip() {
>  
>   local binary strip_flags
>   find . -type f -perm -u+w -print0 2>/dev/null | while IFS= read 
> -rd '' binary ; do
> - case "$(file -bi "$binary")" in
> - *application/x-sharedlib*)  # Libraries (.so)
> + case "$(LC_ALL=C readelf -h "$binary" 2>/dev/null)" in

More squelching of errors.

Incidentally, is the output of this, documented, or can it arbitrarily
change in the future? file is guaranteed to emit output in the
RFC-documented IANA media type format.

> + *Type:*'DYN (Shared object file)'*) # Libraries 
> (.so) or Relocatable binaries
>   strip_flags="$STRIP_SHARED";;
> - *application/x-archive*)# Libraries (.a)
> - strip_flags="$STRIP_STATIC";;
> - *application/x-object*)
> - case "$binary" in
> - *.ko)   # 
> Kernel module
> - 
> strip_flags="$STRIP_SHARED";;
> - *)
> - continue;;
> - esac;;
> - *application/x-executable*) # Binaries
> + *Type:*'EXEC (Executable file)'*) # Binaries
>   strip_flags="$STRIP_BINARIES";;
> - *application/x-pie-executable*)  # Relocatable 
> binaries
> - strip_flags="$STRIP_SHARED";;
> + *Type:*'REL (Relocatable file)'*) # Libraries 
> (.a) or objects
> + if ar t "$binary" &>/dev/null; then # 
> Libraries (.a)
> + strip_flags="$STRIP_STATIC"
> + elif [[ $binary = *'.ko' ]]; then # 
> Kernel module
> + strip_flags="$STRIP_SHARED"
> + else
> + continue
> + fi
> + ;;
>   *)
>   continue ;;
>   esac
> 


-- 
Eli Schwartz
Bug Wrangler and Trusted User



signature.asc
Description: OpenPGP digital signature


Re: [pacman-dev] [PATCH 1/3] libmakepkg: use extraction commands instead of file to find archive type

2019-11-27 Thread Eli Schwartz
On 11/26/19 4:29 PM, Ethan Sommer wrote:
> Previously, to determine which command we should use to extract an
> archive, we would run file and match the output against our list of
> possible extraction commands
> 
> Instead, run the archive through each extraction command's -t (--test)
> flag, if this succeeds then we know that the command is able to extract
> the file and is the one to use

Missing rationale why we care.

>  scripts/libmakepkg/source/file.sh.in | 39 
>  1 file changed, 11 insertions(+), 28 deletions(-)
> 
> diff --git a/scripts/libmakepkg/source/file.sh.in 
> b/scripts/libmakepkg/source/file.sh.in
> index 7297a1c6..faace79b 100644
> --- a/scripts/libmakepkg/source/file.sh.in
> +++ b/scripts/libmakepkg/source/file.sh.in
> @@ -96,35 +96,18 @@ extract_file() {
>   fi
>  
>   # do not rely on extension for file type
> - local file_type=$(@FILECMD@ -bizL -- "$file")
> - local ext=${file##*.}
>   local cmd=''
> - case "$file_type" in
> - 
> *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*)
> - cmd="bsdtar" ;;
> - *application/x-gzip*|*application/gzip*)
> - case "$ext" in
> - gz|z|Z) cmd="gzip" ;;
> - *) return;;
> - esac ;;
> - *application/x-bzip*)
> - case "$ext" in
> - bz2|bz) cmd="bzip2" ;;
> - *) return;;
> - esac ;;
> - *application/x-xz*)
> - case "$ext" in
> - xz) cmd="xz" ;;
> - *) return;;
> - esac ;;
> - *)
> - # See if bsdtar can recognize the file
> - if bsdtar -tf "$file" -q '*' &>/dev/null; then
> - cmd="bsdtar"
> - else
> - return 0
> - fi ;;
> - esac
> + if bsdtar -tf "$file" -q '*'; then
> + cmd='bsdtar'
> + elif gzip -t "$file"; then
> + cmd='gzip'
> + elif bzip2 -t "$file"; then
> + cmd='bzip2'
> + elif xz -t "$file"; then
> + cmd='xz'
> + else
> + return 0
> + fi &>/dev/null

I had to look at this three times before I realized you were redirecting
both stdout and stderr of the entire if/elif block.

Because these commands check to see if the file is "uncorrupted", not to
see if they are "formatted in this compression format", I imagine this
would falsely fail files if they have some class of recoverable error,
but I'm not sure if we care.

What we do care about, I think, is that you're silencing stderr due to
the fact that it will noisily print diagnostic messages when the file is
not compressed or is in a different compression format, and bsdtar will
print listed filenames to stdout. So now, if these commands fail for
*any* reason, we treat this as a successful analysis that the file is in
a different format. One reason for it failing might be that xz is not
installed... this is hardly a successful analysis, and printing an
"error: command not found" message during the decompression, then dying
with "Failed to extract %s" is a desirable feature.

>   local ret=0
>   msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd"
> 


-- 
Eli Schwartz
Bug Wrangler and Trusted User



signature.asc
Description: OpenPGP digital signature