mirror of
https://github.com/moparisthebest/pacman
synced 2025-02-28 09:21:53 -05:00
libalpm: use an lstat wrapper so we never dereference dir symlinks
Linux lstat follows POSIX standards and dereferences a symlink pointing to a directory if there is a trailing slash. For purposes of libalpm, we don't want this so make a lstat wrapper that suppresses this behavior. Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
99f42d6bd2
commit
b55abdce7a
@ -371,7 +371,7 @@ static int extract_single_file(struct archive *archive,
|
||||
* S | 7 | 8 | 9
|
||||
* D | 10 | 11 | 12
|
||||
*
|
||||
* 1,2,3- just extract, no magic necessary. lstat will fail here.
|
||||
* 1,2,3- extract, no magic necessary. lstat (_alpm_lstat) will fail here.
|
||||
* 4,5,6,7,8- conflict checks should have caught this. either overwrite
|
||||
* or backup the file.
|
||||
* 9- follow the symlink, hopefully it is a directory, check it.
|
||||
@ -381,7 +381,7 @@ static int extract_single_file(struct archive *archive,
|
||||
* 12- skip extraction, dir already exists.
|
||||
*/
|
||||
struct stat lsbuf;
|
||||
if(lstat(filename, &lsbuf) != 0) {
|
||||
if(_alpm_lstat(filename, &lsbuf) != 0) {
|
||||
/* cases 1,2,3: couldn't stat an existing file, skip all backup checks */
|
||||
} else {
|
||||
/* do a stat as well, so we can see what symlinks point to */
|
||||
|
@ -334,7 +334,7 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root)
|
||||
snprintf(path, PATH_MAX, "%s%s", root, filestr);
|
||||
|
||||
/* stat the file - if it exists, do some checks */
|
||||
if(lstat(path, &buf) != 0) {
|
||||
if(_alpm_lstat(path, &buf) != 0) {
|
||||
continue;
|
||||
}
|
||||
if(S_ISDIR(buf.st_mode)) {
|
||||
@ -350,7 +350,7 @@ alpm_list_t *_alpm_db_find_conflicts(pmdb_t *db, pmtrans_t *trans, char *root)
|
||||
unsigned ok = 0;
|
||||
for(k = dbpkg->files; k; k = k->next) {
|
||||
snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data);
|
||||
if(!lstat(str, &buf2) && buf.st_ino == buf2.st_ino) {
|
||||
if(!_alpm_lstat(str, &buf2) && buf.st_ino == buf2.st_ino) {
|
||||
ok = 1;
|
||||
_alpm_log(PM_LOG_DEBUG, "conflict was a symlink: %s\n", path);
|
||||
break;
|
||||
|
@ -206,7 +206,7 @@ static void unlink_file(pmpkg_t *info, alpm_list_t *lp, pmtrans_t *trans)
|
||||
}
|
||||
}
|
||||
|
||||
if(lstat(file, &buf)) {
|
||||
if(_alpm_lstat(file, &buf)) {
|
||||
_alpm_log(PM_LOG_DEBUG, "file %s does not exist\n", file);
|
||||
return;
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ int _alpm_rmrf(const char *path)
|
||||
char name[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if(lstat(path, &st) == 0) {
|
||||
if(_alpm_lstat(path, &st) == 0) {
|
||||
if(!S_ISDIR(st.st_mode)) {
|
||||
if(!unlink(path)) {
|
||||
return(0);
|
||||
@ -597,6 +597,30 @@ const char *_alpm_filecache_setup(void)
|
||||
return(alpm_list_getdata(tmp));
|
||||
}
|
||||
|
||||
/** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink.
|
||||
* Linux lstat follows POSIX semantics and still performs a dereference on
|
||||
* the first, and for uses of lstat in libalpm this is not what we want.
|
||||
* @param path path to file to lstat
|
||||
* @param buf structure to fill with stat information
|
||||
* @return the return code from lstat
|
||||
*/
|
||||
int _alpm_lstat(const char *path, struct stat *buf)
|
||||
{
|
||||
int ret;
|
||||
char *newpath = strdup(path);
|
||||
int len = strlen(newpath);
|
||||
|
||||
/* strip the trailing slash if one exists */
|
||||
if(len != 0 && newpath[len - 1] == '/') {
|
||||
newpath[len - 1] = '\0';
|
||||
}
|
||||
|
||||
ret = lstat(path, buf);
|
||||
|
||||
FREE(newpath);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/** Get the md5 sum of file.
|
||||
* @param filename name of the file
|
||||
* @return the checksum on success, NULL on error
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h> /* struct stat */
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
#include <libintl.h> /* here so it doesn't need to be included elsewhere */
|
||||
@ -62,6 +63,7 @@ void _alpm_time2string(time_t t, char *buffer);
|
||||
int _alpm_str_cmp(const void *s1, const void *s2);
|
||||
char *_alpm_filecache_find(const char *filename);
|
||||
const char *_alpm_filecache_setup(void);
|
||||
int _alpm_lstat(const char *path, struct stat *buf);
|
||||
|
||||
#ifndef HAVE_STRVERSCMP
|
||||
int strverscmp(const char *, const char *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user