[pacman-dev] Huge cleanup of add.c and my attempt at fixing FS#7484

Xavier shiningxc at gmail.com
Sun Jul 15 12:45:17 EDT 2007


On Sun, Jul 15, 2007 at 12:09:37PM -0400, Dan McGee wrote:
> > About cases 6 and 10, I agree that conflict checks should catch this,
> > but do they ? (they don't from my understanding of the code)
> 
> Then we should fix that in the conflict check code, probably. I
> haven't looked at it enough.

Ok, I just felt it was important to check that :)

> By the way- is there a reason we even use the filelist provided with
> the package? Any package can lie about it, and since we go though the
> archive once anyway we might as well just use our own generated
> filelist. We can also gather information about each of the files at
> this time (dir, file, symlink, etc.).
> 

I think we could do that. Also that's what Andrew suggested here :
http://www.archlinux.org/pipermail/pacman-dev/2007-July/008867.html

except we maybe don't even need to extract everything to /tmp first.

> > About cases 9 and 11, I think it depends on the nature of the symlink :
> > * if the symlink points to a directory, then skip extraction
> > * if not, then conflict
> 
> If you look at the case 9 code, then you'll see that this is what
> happens, or at least tries to. I'm not sure how effective returning 1
> is by extract_single_file, however it at least spits a warning/error
> here.
> 

Indeed, I just meant that the description in the chart wasn't very clear.
And also, that in the case it doesn't point to a symlink, pacman should
first detect it as a conflict, and simply fails, before it's too late.

> For case 11, we don't care about the nature of the symlink- we want to
> skip extracting the symlink. See the explanation in dpkg code for
> details, which I have put below:
>    *   = If we are trying to install a symlink we do nothing - ie,
>    *     dpkg will never replace a directory tree with a symlink.  This
>    *     is to avoid embarrassing effects such as replacing a directory
>    *     tree with a link to a link to the original directory tree.
> 
> I think this is valid. Perhaps I should put a note like this in the code.
> 

Ah ok, I guess that makes sense.

> In addition, I just realized 10 needs a bit more code to get it to
> work properly, because we would have to unlink an entire directory
> tree. However, this is quite dangerous as well in that it could
> interfere with other packages files. Perhaps we should never allow a
> file to overwrite a directory, even in a force situation? Comments
> welcome.
> 

Indeed, I think we should never allow that.
But unlink and libarchive probably don't as well, they won't remove a whole
directory afaik.
So without --force , pacman should really just fail because of a conflict.
With --force, it doesn't really matter, because unlink and libarchive
should just fail.

> New code comments:
> diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
> index 2c1aa2c..9019c29 100644
> --- a/lib/libalpm/add.c
> +++ b/lib/libalpm/add.c
> @@ -392,9 +392,14 @@ static int extract_single_file(struct archive *archive,
>          *  D            |   10  |  11 |  12
>          *
>          *  1,2,3- just extract, no magic necessary. lstat will fail here.
> -        *  4,5,6,7,8,10- conflict checks should have caught this.
> overwrite/backup.
> -        *  9- follow the symlink, hopefully it is a directory
> -        *  11,12- skip extraction, dir already exists
> +        *  4,5,6,7,8- conflict checks should have caught this. either overwrite
> +        *      or backup the file.

So as said above, 6 needs to be checked so that is true.

> +        *  9- follow the symlink, hopefully it is a directory, check it.
> +        *  10- file replacing directory. a simple unlink probably
> won't work here.
> +        *      TODO handle this case, it is a *very* dangerous one.

Just like 6, this should also fail with a conflict. And if --force flag
is used, unlink and libarchive shouldn't do anything as dangerous as
deleting a whole directory (but maybe double check that).

> +        *  11- don't extract symlink- a dir exists here. we don't want links to
> +        *      links, etc.

Hm, now that I'm looking at this again, I think 10 and 11 should be the same
(file or symlink replacing a directory).

> +        *  12- skip extraction, dir already exists.
>          */
>         struct stat lsbuf;
>         if(lstat(filename, &lsbuf) != 0) {
> 




More information about the pacman-dev mailing list