1
0
mirror of https://github.com/moparisthebest/pacman synced 2024-08-13 17:03:46 -04: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:
Dan McGee 2007-11-04 18:02:25 -06:00
parent 99f42d6bd2
commit b55abdce7a
5 changed files with 32 additions and 6 deletions

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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 *);