Why isn't mkdir -p working right in a script called by checkinstall?
I'm trying to compile Quarter and package it using checkinstall.
If I do the standard ./configure && make && sudo make install, things go fine.
$ wget http://ftp.coin3d.org/coin/src/all/Quarter-1.0.0.tar.gz
$ tar xzf Quarter-1.0.0.tar.gz
$ cd Quarter-1.0.0
$ ./configure
$ make
$ sudo make install
But when I use checkinstall, it fails on a mkdir -p
that should work perfectly fine. The way it fails is exactly how it would as if the -p
option weren't given. This is the checkinstall command line I'm using:
$ checkinstall -D -y --install=no --pkgname=libquarter --pkgversion=1.0.0 \
--arch=i386 --pkglicense=GPL --maintainer=me@example.com --reset-uids=yes
This is the failure:
....
/bin/bash ../../../cfg/mkinstalldirs /usr/local/include/Quarter/devices
mkdir -p -- /usr/local/include/Quarter/devices
mkdir: cannot create directory `/usr/local/include/Quarter': No such file or directory
make[4]: *** [install-libdevicesincHEADERS] Error 1
....
This is the relevant part of the script:
$ cat cfg/mkinstalldirs
....
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
....
I don't understand why that (If the exec
is there -- doesn't that guarantee that the remainder of the script (after the esac
) will never execute?if
test passes, then the script assumes mkdir -p
works correctly, so once it does the real mkdir -p
it can quit; otherwise the remainder of the script implements proper mkdir -p
behavior.) I also don't understand why it uses (Tom explained in comment.)"$*"
in the echo and "$@"
in the next line, but it doesn't seem to matter -- they're both the same thing since this script is being called with just one argument.
If I add two lines between echo
and exec
that does mkdir -p -- "$@"
and then echo "Now doing the exec mkdir..."
then it works like this -- better, but still bewildering:
/bin/bash ../../../cfg/mkinstalldirs /usr/local/include/Quarter/devices
mkdir -p -- /usr/local/include/Quarter/devices
mkdir: cannot create directory `/usr/local/include/Quarter': No such file or directory
Now doing the exec mkdir...
/usr/bin/install -c -m 644 InputDevice.h /usr/local/include/Quarter/devices/InputDevice.h
.... finishes successfully!
Now, the fact that doing the mkdir line twice made it work tells me it's not a permissions issue (beside, that would generate a different diagnostic from mkdir, and this is being run as sudo
, and it's actually working in /var/tmp/...
not the real /usr/local/...
). I think what's happening is that the first mkdir invocation (the one I added) is actually creating just the Quarter
directory and bailing out, and then when the second mkdir runs, it's able to create the devices
subdirectory, because the Quarter directory is already there. But why would mkdir work that way???
My workaround is to patch that mkinstalldirs script somehow, but I'm really curious why this is breaking!
This is a Ubuntu 10.10 guest running in VirtualBox on Win7, checkinstall version 1.6.2 installed thru apt-get.
EDIT: I did some testing to see what works and what fails in this environment...
mkdir -p /foo works correctly
mkdir -p /foo && mkdir -p /foo/bar works correctly
mkdir -p foo/bar works correctly
mkdir /foo/bar fai开发者_StackOverflowled as expected (correct)
mkdir foo/bar failed as expected (correct)
mkdir -p /foo/bar fails
Weird that -p
works for relative pathnames but not for absolute pathnames. Or maybe the correct distinction is that -p
works outside of the "chroot" tree (if it's even really using chroot) but not within it.
I also verified that despite the failure, it is able to create the first directory level.
Still a mystery.
Using
checkinstall --fstrans=no
should fix this. Or
Set "TRANSLATE=0"
in /etc/checkinstallrc
and try again.
mkdir -p
isn't working like it should because it's a checkinstall version of mkdir, not the "true" mkdir. Must be some bug in checkinstall that makes it work a bit differently.
This patch works around the bug:
./configure
sed -i 's/if mkdir .*-p --.*; then/if false; then ## &/' cfg/mkinstalldirs
....
sed -i -e 's/TRANSLATE=1/TRANSLATE=0/g' /etc/checkinstallrc
精彩评论