1#!@prefix@/bin/php -Cq
2<?php // -*- PHP -*-
3
4// {{{ setup
5
6define('S_IFDIR', 0040000); // Directory
7define('S_IFCHR', 0020000); // Character device
8define('S_IFBLK', 0060000); // Block device
9define('S_IFREG', 0100000); // Regular file
10define('S_IFIFO', 0010000); // FIFO
11define('S_IFLNK', 0120000); // Symbolic link
12define('S_IFSOCK', 0140000); // Socket
13
14require_once "PEAR.php";
15require_once "Archive/Tar.php";
16require_once "Console/Getopt.php";
17
18// }}}
19// {{{ options
20
21$verbose    = false;
22$op_create  = false;
23$op_list    = false;
24$op_extract = false;
25$use_gzip   = false;
26$file       = '';
27
28$progname = basename(array_shift($argv));
29
30$options = Console_Getopt::getopt($argv, "h?ctxvzf:");
31if (PEAR::isError($options)) {
32    usage($options);
33}
34
35$opts = $options[0];
36foreach ($opts as $opt) {
37    switch ($opt[0]) {
38        case 'v': {
39            $verbose = true;
40            break;
41        }
42        case 'c': {
43            $op_create = true;
44            break;
45        }
46        case 't': {
47            $op_list = true;
48            break;
49        }
50        case 'x': {
51            $op_extract = true;
52            break;
53        }
54        case 'z': {
55            $use_gzip = true;
56            break;
57        }
58        case 'f': {
59            $file = $opt[1];
60            break;
61        }
62        case 'h':
63        case '?': {
64            usage();
65            break;
66        }
67    }
68}
69
70if ($op_create + $op_list + $op_extract > 1) {
71    usage("Only one of -c, -t and -x can be specified at once!");
72}
73
74if ($op_create + $op_list + $op_extract == 0) {
75    usage("Please specify either -c, -t or -x!");
76}
77
78if (empty($file)) {
79    if ($op_create) {
80        $file = "php://stdout";
81    } else {
82        $file = "php://stdin";
83    }
84}
85
86// }}}
87
88$tar = new Archive_Tar($file, $use_gzip);
89$tar->setErrorHandling(PEAR_ERROR_DIE, "$progname error: %s\n");
90
91if ($op_create) {
92    do_create($tar, $options[1]);
93    $tar->create($options[1]);
94} elseif ($op_list) {
95    do_list($tar, $verbose);
96} elseif ($op_extract) {
97    do_extract($tar);
98}
99
100// {{{ getrwx()
101
102function getrwx($bits) {
103    $str = '';
104    $str .= ($bits & 4) ? 'r' : '-';
105    $str .= ($bits & 2) ? 'w' : '-';
106    $str .= ($bits & 1) ? 'x' : '-';
107    return $str;
108}
109
110// }}}
111// {{{ getfiletype()
112
113function getfiletype($bits) {
114    static $map = array(
115        '-' => S_IFREG,
116        'd' => S_IFDIR,
117        'l' => S_IFLNK,
118        'c' => S_IFCHR,
119        'b' => S_IFBLK,
120        'p' => S_IFIFO,
121        's' => S_IFSOCK,
122        );
123    foreach ($map as $char => $mask) {
124        if ($bits & $mask) {
125            return $char;
126        }
127    }
128}
129
130// }}}
131// {{{ getuser()
132
133function getuser($uid) {
134    static $cache = array();
135    if (isset($cache[$uid])) {
136        return $cache[$uid];
137    }
138    if (function_exists("posix_getpwuid")) {
139        if (is_array($user = @posix_getpwuid($uid))) {
140            $cache[$uid] = $user['name'];
141            return $user['name'];
142        }
143    }
144    $cache[$uid] = $uid;
145    return $uid;
146}
147
148// }}}
149// {{{ getgroup()
150
151function getgroup($gid) {
152    static $cache = array();
153    if (isset($cache[$gid])) {
154        return $cache[$gid];
155    }
156    if (function_exists("posix_getgrgid")) {
157        if (is_array($group = @posix_getgrgid($gid))) {
158            $cache[$gid] = $group['name'];
159            return $group['name'];
160        }
161    }
162    $cache[$gid] = $gid;
163    return $gid;
164}
165
166// }}}
167// {{{ do_create()
168
169function do_create(&$tar, &$files)
170{
171    $tar->create($files);
172}
173
174// }}}
175// {{{ do_list()
176
177function do_list(&$tar, $verbose)
178{
179    static $rwx = array(4 => 'r', 2 => 'w', 1 => 'x');
180    $files = $tar->listContent();
181    if (is_array($files) && sizeof($files) > 0) {
182        foreach ($files as $file) {
183            if ($verbose) {
184                $fm = (int)$file['mode'];
185                $mode = sprintf('%s%s%s%s', getfiletype($fm),
186                                getrwx(($fm >> 6) & 7), getrwx(($fm >> 3) & 7),
187                                getrwx($fm & 7));
188                $owner = getuser($file['uid']) . '/' . getgroup($file['gid']);
189                printf("%10s %-11s %7d %s %s\n", $mode, $owner, $file['size'],
190                       date('Y-m-d H:i:s', $file['mtime']), $file['filename']);
191            } else {
192                printf("%s\n", $file['filename']);
193            }
194        }
195    }
196}
197
198// }}}
199// {{{ do_extract()
200
201function do_extract(&$tar, $destdir = ".")
202{
203    $tar->extract($destdir);
204}
205
206// }}}
207// {{{ usage()
208
209function usage($errormsg = '')
210{
211    global $progname;
212    $fp = fopen("php://stderr", "w");
213    if ($errormsg) {
214        if (PEAR::isError($errormsg)) {
215            fwrite($fp, $errormsg->getMessage() . "\n");
216        } else {
217            fwrite($fp, "$errormsg\n");
218        }
219    }
220    fwrite($fp, "$progname [-h|-?] {-c|-t|-x} [-z] [-v] [-f file] [file(s)...]
221Options:
222      -h, -?   Show this screen
223      -c       Create archive
224      -t       List archive
225      -x       Extract archive
226      -z       Run input/output through gzip
227      -f file  Use <file> as input or output (default is stdin/stdout)
228
229");
230    fclose($fp);
231    exit;
232}
233
234// }}}
235
236?>
237