php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67943 Files written outside INSTALL_ROOT install
Submitted: 2014-09-01 14:31 UTC Modified: 2014-09-01 14:54 UTC
From: phpbug at monumentmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 5.6.0 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: phpbug at monumentmail dot com
New email:
PHP Version: OS:

 

 [2014-09-01 14:31 UTC] 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



Patches

patch1.patch (last revision 2014-09-01 14:34 UTC by phpbug at monumentmail dot com)
patch2.patch (last revision 2014-09-01 14:32 UTC by phpbug at monumentmail dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-09-01 14:54 UTC] johannes@php.net
-Status: Open +Status: Not a bug
 [2014-09-01 14:54 UTC] johannes@php.net
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!
 [2014-09-01 15:08 UTC] phpbug at mailinator dot com
Ok, have done so.
For further reference, it is 20383 on pear
https://pear.php.net/bugs/bug.php?&id=20383
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Wed Oct 07 11:00:02 2026 UTC