Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 *  $Id: UnixFileSystem.php 258 2007-10-21 00:46:45Z hans $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information please see
19
 * <http://phing.info>.
20
 */
21
 
22
include_once 'phing/system/io/FileSystem.php';
23
 
24
/**
25
 * UnixFileSystem class. This class encapsulates the basic file system functions
26
 * for platforms using the unix (posix)-stylish filesystem. It wraps php native
27
 * functions suppressing normal PHP error reporting and instead uses Exception
28
 * to report and error.
29
 *
30
 * This class is part of a oop based filesystem abstraction and targeted to run
31
 * on all supported php platforms.
32
 *
33
 * Note: For debugging turn track_errors on in the php.ini. The error messages
34
 * and log messages from this class will then be clearer because $php_errormsg
35
 * is passed as part of the message.
36
 *
37
 * FIXME:
38
 *  - Comments
39
 *  - Error handling reduced to min, error are handled by PhingFile mainly
40
 *
41
 * @author    Andreas Aderhold, andi@binarycloud.com
42
 * @version   $Revision: 1.10 $
43
 * @package   phing.system.io
44
 */
45
class UnixFileSystem extends FileSystem {
46
 
47
    /**
48
     * returns OS dependant path separator char
49
     */
50
    function getSeparator() {
51
        return '/';
52
    }
53
 
54
    /**
55
     * returns OS dependant directory separator char
56
     */
57
    function getPathSeparator() {
58
        return ':';
59
    }
60
 
61
    /**
62
     * A normal Unix pathname contains no duplicate slashes and does not end
63
     * with a slash.  It may be the empty string.
64
     *
65
     * Check that the given pathname is normal.  If not, invoke the real
66
     * normalizer on the part of the pathname that requires normalization.
67
     * This way we iterate through the whole pathname string only once.
68
     */
69
    function normalize($strPathname) {
70
 
71
        if (empty($strPathname)) {
72
            return;
73
        }
74
 
75
        // Resolve home directories. We assume /home is where all home
76
        // directories reside, b/c there is no other way to do this with
77
        // PHP AFAIK.
78
        if ($strPathname{0} === "~") {
79
            if ($strPathname{1} === "/") { // like ~/foo => /home/user/foo
80
                $strPathname = "/home/" . get_current_user() . substr($strPathname, 1);
81
            } else { // like ~foo => /home/foo
82
                $pos = strpos($strPathname, "/");
83
                $name = substr($strPathname, 1, $pos - 2);
84
                $strPathname = "/home/" . $name . substr($strPathname, $pos);
85
            }
86
        }
87
 
88
        $n = strlen($strPathname);
89
        $prevChar = 0;
90
        for ($i=0; $i < $n; $i++) {
91
            $c = $strPathname{$i};
92
            if (($prevChar === '/') && ($c === '/')) {
93
                return self::normalizer($strPathname, $n, $i - 1);
94
            }
95
            $prevChar = $c;
96
        }
97
        if ($prevChar === '/') {
98
            return self::normalizer($strPathname, $n, $n - 1);
99
        }
100
        return $strPathname;
101
    }
102
 
103
    /**
104
     * Normalize the given pathname, whose length is $len, starting at the given
105
     * $offset; everything before this offset is already normal.
106
     */
107
    protected function normalizer($pathname, $len, $offset) {
108
        if ($len === 0) {
109
            return $pathname;
110
        }
111
        $n = (int) $len;
112
        while (($n > 0) && ($pathname{$n-1} === '/')) {
113
            $n--;
114
        }
115
        if ($n === 0) {
116
            return '/';
117
        }
118
        $sb = "";
119
 
120
        if ($offset > 0) {
121
            $sb .= substr($pathname, 0, $offset);
122
        }
123
        $prevChar = 0;
124
        for ($i = $offset; $i < $n; $i++) {
125
            $c = $pathname{$i};
126
            if (($prevChar === '/') && ($c === '/')) {
127
                continue;
128
            }
129
            $sb .= $c;
130
            $prevChar = $c;
131
        }
132
        return $sb;
133
    }
134
 
135
    /**
136
     * Compute the length of the pathname string's prefix.  The pathname
137
     * string must be in normal form.
138
     */
139
    function prefixLength($pathname) {
140
        if (strlen($pathname === 0)) {
141
            return 0;
142
        }
143
        return (($pathname{0} === '/') ? 1 : 0);
144
    }
145
 
146
    /**
147
     * Resolve the child pathname string against the parent.
148
     * Both strings must be in normal form, and the result
149
     * will be in normal form.
150
     */
151
    function resolve($parent, $child) {
152
 
153
        if ($child === "") {
154
            return $parent;
155
        }
156
 
157
        if ($child{0} === '/') {
158
            if ($parent === '/') {
159
                return $child;
160
            }
161
            return $parent.$child;
162
        }
163
 
164
        if ($parent === '/') {
165
            return $parent.$child;
166
        }
167
 
168
        return $parent.'/'.$child;
169
    }
170
 
171
    function getDefaultParent() {
172
        return '/';
173
    }
174
 
175
    function isAbsolute(PhingFile $f) {
176
        return ($f->getPrefixLength() !== 0);
177
    }
178
 
179
    /**
180
     * the file resolver
181
     */
182
    function resolveFile(PhingFile $f) {
183
        // resolve if parent is a file oject only
184
        if ($this->isAbsolute($f)) {
185
            return $f->getPath();
186
        } else {
187
            return $this->resolve(Phing::getProperty("user.dir"), $f->getPath());
188
        }
189
    }
190
 
191
    /* -- most of the following is mapped to the php natives wrapped by FileSystem */
192
 
193
    /* -- Attribute accessors -- */
194
    function getBooleanAttributes(&$f) {
195
        //$rv = getBooleanAttributes0($f);
196
        $name = $f->getName();
197
        $hidden = (strlen($name) > 0) && ($name{0} == '.');
198
        return ($hidden ? $this->BA_HIDDEN : 0);
199
    }
200
 
201
    /**
202
     * set file readonly on unix
203
     */
204
    function setReadOnly($f) {
205
        if ($f instanceof File) {
206
            $strPath = (string) $f->getPath();
207
            $perms = (int) (@fileperms($strPath) & 0444);
208
            return FileSystem::Chmod($strPath, $perms);
209
        } else {
210
            throw new Exception("IllegalArgutmentType: Argument is not File");
211
        }
212
    }
213
 
214
    /**
215
     * compares file paths lexicographically
216
     */
217
    function compare($f1, $f2) {
218
        if ( ($f1 instanceof PhingFile) && ($f2 instanceof PhingFile) ) {
219
            $f1Path = $f1->getPath();
220
            $f2Path = $f2->getPath();
221
            return (boolean) strcmp((string) $f1Path, (string) $f2Path);
222
        } else {
223
            throw new Exception("IllegalArgutmentType: Argument is not PhingFile");
224
        }
225
    }
226
 
227
    /* -- fs interface --*/
228
 
229
    function listRoots() {
230
        if (!$this->checkAccess('/', false)) {
231
            die ("Can not access root");
232
        }
233
        return array(new PhingFile("/"));
234
    }
235
 
236
    /**
237
     * returns the contents of a directory in an array
238
     */
239
    function lister($f) {
240
        $dir = @opendir($f->getAbsolutePath());
241
        if (!$dir) {
242
            throw new Exception("Can't open directory " . $f->__toString());
243
        }
244
        $vv = array();
245
        while (($file = @readdir($dir)) !== false) {
246
            if ($file == "." || $file == "..") {
247
                continue;
248
            }
249
            $vv[] = (string) $file;
250
        }
251
        @closedir($dir);
252
        return $vv;
253
    }
254
 
255
    function fromURIPath($p) {
256
        if (StringHelper::endsWith("/", $p) && (strlen($p) > 1)) {
257
 
258
            // "/foo/" --> "/foo", but "/" --> "/"
259
            $p = substr($p, 0, strlen($p) - 1);
260
 
261
        }
262
 
263
        return $p;
264
    }
265
 
266
    /**
267
     * Whether file can be deleted.
268
     * @param PhingFile $f
269
     * @return boolean
270
     */
271
    function canDelete(PhingFile $f)
272
 	{
273
 		@clearstatcache();
274
 		$dir = dirname($f->getAbsolutePath());
275
 		return (bool) @is_writable($dir);
276
	}
277
 
278
}