Bug #67943 [Opn->Nab]: Files written outside INSTALL_ROOT install

From: Date: Mon, 01 Sep 2014 14:54:28 +0000
Subject: Bug #67943 [Opn->Nab]: Files written outside INSTALL_ROOT install
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-187367@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=67943&edit=1 ID: 67943 Updated by: johannes@php.net Reported by: phpbug at monumentmail dot com Summary: Files written outside INSTALL_ROOT install -Status: Open +Status: Not a bug Type: Bug Package: *General Issues Operating System: Linux PHP Version: 5.6.0 Block user comment: N Private report: N New Comment: This has to be reported to PEAR as a bug. We don't have a automatic migration so please enter it at https://pear.php.net/bugs/report.php?package=PEAR&action=Report+Bug again so you'll keep getting updates as reporter there. Sorry for the inconvenience and thanks for your research and help! Previous Comments: ------------------------------------------------------------------------ [2014-09-01 14:31:38] phpbug at monumentmail dot com Description: ------------ See the following 'standard' install sequence with an INSTALL_ROOT. The result is 2 PEAR databases created where they should not have been. One is outside the INSTALL_ROOT, on the location where it would have been. The other is in the root of INSTALL_ROOT itself. This problem is also present in the 5.5.*, 5.4.* and 5.3.* branches. Analysis of this is below the example. test:~/php-5.6.0$ ./configure --prefix=$HOME/php test:~/php-5.6.0$ make test:~/php-5.6.0$ ls -l $HOME total 4 drwxr-xr-x 17 test users 4096 Sep 1 08:00 php-5.6.0/ test:~/php-5.6.0$ make install INSTALL_ROOT=$HOME/staging test:~/php-5.6.0$ ls -al $HOME total 12 drwxr-xr-x 3 test users 4096 Sep 1 08:02 php/ drwxr-xr-x 17 test users 4096 Sep 1 08:00 php-5.6.0/ drwxr-xr-x 5 test users 4096 Sep 1 08:02 staging/ -- The php directory should not have been created here, as we installed with INSTALL_ROOT. test:~/php-5.6.0$ find $HOME/php /home/test/php /home/test/php/lib /home/test/php/lib/php /home/test/php/lib/php/.depdb /home/test/php/lib/php/.filemap /home/test/php/lib/php/.depdblock /home/test/php/lib/php/.lock /home/test/php/lib/php/.registry /home/test/php/lib/php/.registry/.channel.__uri /home/test/php/lib/php/.registry/.channel.pecl.php.net /home/test/php/lib/php/.registry/.channel.doc.php.net /home/test/php/lib/php/.channels /home/test/php/lib/php/.channels/doc.php.net.reg /home/test/php/lib/php/.channels/__uri.reg /home/test/php/lib/php/.channels/pear.php.net.reg /home/test/php/lib/php/.channels/.alias /home/test/php/lib/php/.channels/.alias/phpdocs.txt /home/test/php/lib/php/.channels/.alias/pear.txt /home/test/php/lib/php/.channels/.alias/pecl.txt /home/test/php/lib/php/.channels/pecl.php.net.reg -- This is an empty PEAR database test:~/php-5.6.0$ find $HOME/staging /home/test/staging /home/test/staging/.depdb /home/test/staging/.filemap /home/test/staging/.depdblock /home/test/staging/.lock /home/test/staging/.registry /home/test/staging/.registry/.channel.__uri /home/test/staging/.registry/.channel.pecl.php.net /home/test/staging/.registry/.channel.doc.php.net /home/test/staging/home /home/test/staging/home/test /home/test/staging/home/test/php /home/test/staging/home/test/php/etc /home/test/staging/home/test/php/etc/pear.conf ... ... /home/test/staging/home/test/php/bin/php-cgi /home/test/staging/home/test/php/bin/php /home/test/staging/.channels /home/test/staging/.channels/doc.php.net.reg /home/test/staging/.channels/__uri.reg /home/test/staging/.channels/pear.php.net.reg /home/test/staging/.channels/.alias /home/test/staging/.channels/.alias/phpdocs.txt /home/test/staging/.channels/.alias/pear.txt /home/test/staging/.channels/.alias/pecl.txt /home/test/staging/.channels/pecl.php.net.reg -- And a second empty PEAR database in the root of the staging directory. -- The correct PEAR database is at '/home/test/staging/home/test/php/lib/php/'. -- The sub install command 'make install-pear INSTALL_ROOT=$HOME/staging' gives the same result. I have tried to find out what caused this behavior and it stems from the PEAR installation file located at 'php-5.6.0/pear/install-pear-nozlib.phar'. Trying to pinpoint it, it seems to always get back to some logic in 'PEAR/Registry.php' in this archive. In normal operation (no INSTALL_ROOT), there are only 2 registry objects made, with proper paths. However, with the use of INSTALL_ROOT, the registry objects seem to be recreated constantly, with different paths to the php root, and by different objects in the PEAR installation. These recreations eventually lead to assertion of paths, usually by locking or re-locking of the registry databases, which then create the database if it does not exist. I could trace the creation of the database in the root of INSTALL_ROOT on line 208 in index.php: $reg = &new PEAR_Registry($options['packagingroot']); I fixed this with: $reg = &new PEAR_Registry($options['packagingroot'] . DIRECTORY_SEPARATOR . $config->get('php_dir')); This seems to be ok, for as far as I can understand what is going on, and it seems to fit the logic. This fix is found in patch1.patch, but I must note that I have absolutely no experience with the inner working of the PEAR code, so I have no idea if this is indeed the logic and proper fix. I did add a small cosmetic patch to this patch too (see below). For the other surplus database, created outside the INSTALL_ROOT all together, I know that the fix I have created is completely wrong (patch2.patch). The recreation of the registry objects is all over the place, and as I said, having no experience with the inner workings of PEAR, I have no idea what is right and what is not. The patch I have created merely fixes the symptoms, mostly by just disabling locking and some changes to other places. I think, or at least I deduced from the call stacks which get to the lock, that the recreation of the registry objects themselves are likely the real problem, but my attempts to fix it like that all ave stranded into nothingness. A small snippet of code I used is the following: print "---- setInstallDir() $pear_install_dir\n"; $trace = debug_backtrace(); for ($i = 0; $i < count($trace); $i++) print $trace[$i]["file"] . ":" . $trace[$i]["function"] . " (" . $trace[$i]["line"] . ")\n"; I put this at various entries of functions to get the said call stacks, especially at setInstallDir(), the various _assert*Dir() and _lock(). The first line obviously changed to indicate the current function, and the path of intrest (like $this->install_dir in case of some of the asserts). The difference between a make install without INSTALL_ROOT and with is quite striking, especially with regard to the calling of setInstallDir(), which is mainly (exclusively?) called by the constructor. One of the things I did notice was that the paths in the $config object (in installer.php) seemingly gets changed after the 1st iteration in the foreach loop. The fix I applied is an extreme hack, I failed to track down why it changed. So, final words, I have no idea how to fix this properly, but I hope I have given an adequate description of the problem and did some proper analyzing of the root cause. I'm of course more then happy to do some more digging if required, but it probably is best if someone who actually knows how PEAR is supposed to work can look at it, or at least give some idea on how to proceed. The small cosmetic thing: [PEAR] Archive_Tar - installed: 1.3.12 [PEAR] Console_Getopt - installed: 1.3.1 [PEAR] Structures_Graph- installed: 1.0.4 [PEAR] XML_Util - installed: 1.2.3 [PEAR] PEAR - installed: 1.9.5 The Structures_Graph is longer then the rest and touches the dash, so I guess 2 spaces need to be added to the lines. I fixed this in patch1.patch too, as stated above. ps. I have not tried it, and I have no idea if things actually work like this, but it seems that the runtime PEAR inside the phar archive itself is not the same version as the tarred one which get installed. If there is a bug in the runtime version, it likely is also in the 1.9.5 version? Or could it be fixed there? Or is that tarred version not usable as a 'bootstrap' version as in the phar? (As I said, I really don't know how PEAR works, just guessing a bit here.) (I see that I can only add 1 patch, so below is patch1.patch) --- 1/index.php 2014-08-31 10:46:49.117195207 +0200 +++ 2/index.php 2014-09-01 11:39:30.000000000 +0200 @@ -205,7 +205,7 @@ $install_root = getenv('INSTALL_ROOT'); if (!empty($install_root)) { $options['packagingroot'] = $install_root; - $reg = &new PEAR_Registry($options['packagingroot']); + $reg = &new PEAR_Registry($options['packagingroot'] . DIRECTORY_SEPARATOR . $config->get('php_dir')); } else { $reg = $config->getRegistry('default'); } @@ -246,7 +246,7 @@ $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage())); continue; } - $ui->outputData(sprintf("[PEAR] %-15s- upgraded: %s", $package, $new_ver)); + $ui->outputData(sprintf("[PEAR] %-17s- upgraded: %s", $package, $new_ver)); } else { if ($force) { $options['force'] = true; @@ -258,9 +258,9 @@ $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage())); continue; } - $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver)); + $ui->outputData(sprintf("[PEAR] %-17s- installed: %s", $package, $new_ver)); } else { - $ui->outputData(sprintf("[PEAR] %-15s- already installed: %s", $package, $old_ver)); + $ui->outputData(sprintf("[PEAR] %-17s- already installed: %s", $package, $old_ver)); } } } else { @@ -273,7 +273,7 @@ $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage())); continue; } - $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver)); + $ui->outputData(sprintf("[PEAR] %-17s- installed: %s", $package, $new_ver)); } if ($package == 'PEAR') { if (is_file($ufile = $config->getConfFile('user'))) { Test script: --------------- ./configure --prefix=$HOME/php make make install INSTALL_ROOT=$HOME/staging ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=67943&edit=1

« previous php.bugs (#187367) next »