989b321e9828b694c19dacf27aa65ade7aa8b92d
2 // --------------------------------------------------------------------------------
3 // PhpConcept Library - Tar Module 1.3.1
4 // --------------------------------------------------------------------------------
5 // License GNU/GPL - Vincent Blavet - January 2003
6 // http://www.phpconcept.net
7 // --------------------------------------------------------------------------------
10 // PclTar is a library that allow you to create a GNU TAR + GNU ZIP archive,
11 // to add files or directories, to extract all the archive or a part of it.
12 // So far tests show that the files generated by PclTar are readable by
13 // gzip tools and WinZip application.
16 // See readme.txt (English & Fran�ais) and http://www.phpconcept.net
19 // This library and the associated files are non commercial, non professional
21 // It should not have unexpected results. However if any damage is caused by
22 // this software the author can not be responsible.
23 // The use of this software is at the risk of the user.
25 // --------------------------------------------------------------------------------
27 // ----- Look for double include
28 if (!defined("PCL_TAR")) {
31 // ----- Configuration variable
32 // Theses values may be changed by the user of PclTar library
33 if (!isset($g_pcltar_lib_dir)) {
34 $g_pcltar_lib_dir = find_in_path("lib/pcltar");
38 // -1 : Unable to open file in binary write mode
39 // -2 : Unable to open file in binary read mode
40 // -3 : Invalid parameters
41 // -4 : File does not exist
42 // -5 : Filename is too long (max. 99)
43 // -6 : Not a valid tar file
44 // -7 : Invalid extracted file size
45 // -8 : Unable to create directory
46 // -9 : Invalid archive extension
47 // -10 : Invalid archive format
48 // -11 : Unable to delete file (unlink)
49 // -12 : Unable to rename file (rename)
50 // -13 : Invalid header checksum
53 // --------------------------------------------------------------------------------
54 // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
55 // --------------------------------------------------------------------------------
57 // ----- Global variables
58 $g_pcltar_version = "1.3.1";
60 // ----- Extract extension type (.php3/.php/...)
61 $g_pcltar_extension = "php";
63 // ----- Include other libraries
64 // This library should be called by each script before the include of PhpZip
65 // Library in order to limit the potential 'lib' directory path problem.
66 if (!defined("PCLERROR_LIB")) {
67 include($g_pcltar_lib_dir . "/pclerror.lib." . $g_pcltar_extension);
69 if (!defined("PCLTRACE_LIB")) {
70 include($g_pcltar_lib_dir . "/pcltrace.lib." . $g_pcltar_extension);
73 // --------------------------------------------------------------------------------
74 // Function : PclTarCreate()
76 // Creates a new archive with name $p_tarname containing the files and/or
77 // directories indicated in $p_list. If the tar filename extension is
78 // ".tar", the file will not be compressed. If it is ".tar.gz" or ".tgz"
79 // it will be a gzip compressed tar archive.
80 // If you want to use an other extension, you must indicate the mode in
81 // $p_mode ("tar" or "tgz").
82 // $p_add_dir and $p_remove_dir give you the ability to store a path
83 // which is not the real path of the files.
85 // $p_tarname : Name of an existing tar file
86 // $p_filelist : An array containing file or directory names, or
87 // a string containing one filename or directory name, or
88 // a string containing a list of filenames and/or directory
89 // names separated by spaces.
90 // $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive,
91 // if $p_mode is not specified, it will be determined by the extension.
92 // $p_add_dir : Path to add in the filename path archived
93 // $p_remove_dir : Path to remove in the filename path archived
95 // 1 on success, or an error code (see table at the beginning).
96 // --------------------------------------------------------------------------------
97 function PclTarCreate($p_tarname, $p_filelist = "", $p_mode = "", $p_add_dir = "", $p_remove_dir = "") {
98 TrFctStart(__FILE__
, __LINE__
, "PclTarCreate",
99 "tar=$p_tarname, file='$p_filelist', mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
102 // ----- Look for default mode
103 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
104 // ----- Extract the tar format from the extension
105 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
107 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
109 return PclErrorCode();
113 TrFctMessage(__FILE__
, __LINE__
, 1, "Auto mode selected : found $p_mode");
116 // ----- Look if the $p_filelist is really an array
117 if (is_array($p_filelist)) {
118 // ----- Call the create fct
119 $v_result = PclTarHandleCreate($p_tarname, $p_filelist, $p_mode, $p_add_dir, $p_remove_dir);
120 } // ----- Look if the $p_filelist is a string
122 if (is_string($p_filelist)) {
123 // ----- Create a list with the elements from the string
124 $v_list = explode(" ", $p_filelist);
126 // ----- Call the create fct
127 $v_result = PclTarHandleCreate($p_tarname, $v_list, $p_mode, $p_add_dir, $p_remove_dir);
128 } // ----- Invalid variable
131 PclErrorLog(-3, "Invalid variable type p_filelist");
137 TrFctEnd(__FILE__
, __LINE__
, $v_result);
142 // --------------------------------------------------------------------------------
144 // --------------------------------------------------------------------------------
145 // Function : PclTarAdd()
147 // PLEASE DO NOT USE ANY MORE THIS FUNCTION. Use PclTarAddList().
149 // This function is maintained only for compatibility reason
152 // $p_tarname : Name of an existing tar file
153 // $p_filelist : An array containing file or directory names, or
154 // a string containing one filename or directory name, or
155 // a string containing a list of filenames and/or directory
156 // names separated by spaces.
159 // Or an error code (see list on top).
160 // --------------------------------------------------------------------------------
161 function PclTarAdd($p_tarname, $p_filelist) {
162 TrFctStart(__FILE__
, __LINE__
, "PclTarAdd", "tar=$p_tarname, file=$p_filelist");
164 $v_list_detail = array();
166 // ----- Extract the tar format from the extension
167 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
169 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
171 return PclErrorCode();
174 // ----- Look if the $p_filelist is really an array
175 if (is_array($p_filelist)) {
176 // ----- Call the add fct
177 $v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $v_list_detail, "", "");
178 } // ----- Look if the $p_filelist is a string
180 if (is_string($p_filelist)) {
181 // ----- Create a list with the elements from the string
182 $v_list = explode(" ", $p_filelist);
184 // ----- Call the add fct
185 $v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $v_list_detail, "", "");
186 } // ----- Invalid variable
189 PclErrorLog(-3, "Invalid variable type p_filelist");
195 unset($v_list_detail);
198 TrFctEnd(__FILE__
, __LINE__
, $v_result);
203 // --------------------------------------------------------------------------------
205 // --------------------------------------------------------------------------------
206 // Function : PclTarAddList()
208 // Add a list of files or directories ($p_filelist) in the tar archive $p_tarname.
209 // The list can be an array of file/directory names or a string with names
210 // separated by one space.
211 // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
212 // different from the real path of the file. This is usefull if you want to have PclTar
213 // running in any directory, and memorize relative path from an other directory.
214 // If $p_mode is not set it will be automatically computed from the $p_tarname
215 // extension (.tar, .tar.gz or .tgz).
217 // $p_tarname : Name of an existing tar file
218 // $p_filelist : An array containing file or directory names, or
219 // a string containing one filename or directory name, or
220 // a string containing a list of filenames and/or directory
221 // names separated by spaces.
222 // $p_add_dir : Path to add in the filename path archived
223 // $p_remove_dir : Path to remove in the filename path archived
224 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
227 // Or an error code (see list on top).
228 // --------------------------------------------------------------------------------
229 function PclTarAddList($p_tarname, $p_filelist, $p_add_dir = "", $p_remove_dir = "", $p_mode = "") {
230 TrFctStart(__FILE__
, __LINE__
, "PclTarAddList",
231 "tar=$p_tarname, file=$p_filelist, p_add_dir='$p_add_dir', p_remove_dir='$p_remove_dir', mode=$p_mode");
233 $p_list_detail = array();
235 // ----- Extract the tar format from the extension
236 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
237 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
239 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
241 return PclErrorCode();
245 // ----- Look if the $p_filelist is really an array
246 if (is_array($p_filelist)) {
247 // ----- Call the add fct
248 $v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
249 } // ----- Look if the $p_filelist is a string
251 if (is_string($p_filelist)) {
252 // ----- Create a list with the elements from the string
253 $v_list = explode(" ", $p_filelist);
255 // ----- Call the add fct
256 $v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
257 } // ----- Invalid variable
260 PclErrorLog(-3, "Invalid variable type p_filelist");
266 if ($v_result != 1) {
267 TrFctEnd(__FILE__
, __LINE__
, 0);
271 TrFctEnd(__FILE__
, __LINE__
, $p_list_detail);
273 return $p_list_detail;
276 // --------------------------------------------------------------------------------
278 // --------------------------------------------------------------------------------
279 // Function : PclTarList()
281 // Gives the list of all the files present in the tar archive $p_tarname.
282 // The list is the function result, it will be 0 on error.
283 // Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
284 // function will determine the type of the archive.
286 // $p_tarname : Name of an existing tar file
287 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
289 // 0 on error (Use PclErrorCode() and PclErrorString() for more info)
291 // An array containing file properties. Each file properties is an array of
293 // The properties (array field names) are :
294 // filename, size, mode, uid, gid, mtime, typeflag, status
295 // Exemple : $v_list = PclTarList("my.tar");
296 // for ($i=0; $i<sizeof($v_list); $i++)
297 // echo "Filename :'".$v_list[$i]['filename']."'<br>";
298 // --------------------------------------------------------------------------------
299 function PclTarList($p_tarname, $p_mode = "") {
300 TrFctStart(__FILE__
, __LINE__
, "PclTarList", "tar=$p_tarname, mode='$p_mode'");
303 // ----- Extract the tar format from the extension
304 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
305 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
307 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
313 // ----- Call the extracting fct
315 if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, "list", "", $p_mode, "")) != 1) {
317 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
323 TrFctEnd(__FILE__
, __LINE__
, $p_list);
328 // --------------------------------------------------------------------------------
330 // --------------------------------------------------------------------------------
331 // Function : PclTarExtract()
333 // Extract all the files present in the archive $p_tarname, in the directory
334 // $p_path. The relative path of the archived files are keep and become
335 // relative to $p_path.
336 // If a file with the same name already exists it will be replaced.
337 // If the path to the file does not exist, it will be created.
338 // Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
339 // function will determine the type of the archive.
341 // $p_tarname : Name of an existing tar file.
342 // $p_path : Path where the files will be extracted. The files will use
343 // their memorized path from $p_path.
344 // If $p_path is "", files will be extracted in "./".
345 // $p_remove_path : Path to remove (from the file memorized path) while writing the
346 // extracted files. If the path does not match the file path,
347 // the file is extracted with its memorized path.
348 // $p_path and $p_remove_path are commulative.
349 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
351 // Same as PclTarList()
352 // --------------------------------------------------------------------------------
353 function PclTarExtract($p_tarname, $p_path = "./", $p_remove_path = "", $p_mode = "") {
354 TrFctStart(__FILE__
, __LINE__
, "PclTarExtract",
355 "tar='$p_tarname', path='$p_path', remove_path='$p_remove_path', mode='$p_mode'");
358 // ----- Extract the tar format from the extension
359 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
360 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
362 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
368 // ----- Call the extracting fct
369 if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, "complete", $p_path, $p_mode,
370 $p_remove_path)) != 1
372 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
378 TrFctEnd(__FILE__
, __LINE__
, $p_list);
383 // --------------------------------------------------------------------------------
385 // --------------------------------------------------------------------------------
386 // Function : PclTarExtractList()
388 // Extract the files present in the archive $p_tarname and specified in
389 // $p_filelist, in the directory
390 // $p_path. The relative path of the archived files are keep and become
391 // relative to $p_path.
392 // If a directory is sp�cified in the list, all the files from this directory
393 // will be extracted.
394 // If a file with the same name already exists it will be replaced.
395 // If the path to the file does not exist, it will be created.
396 // Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
397 // function will determine the type of the archive.
399 // $p_tarname : Name of an existing tar file
400 // $p_filelist : An array containing file or directory names, or
401 // a string containing one filename or directory name, or
402 // a string containing a list of filenames and/or directory
403 // names separated by spaces.
404 // $p_path : Path where the files will be extracted. The files will use
405 // their memorized path from $p_path.
406 // If $p_path is "", files will be extracted in "./".
407 // $p_remove_path : Path to remove (from the file memorized path) while writing the
408 // extracted files. If the path does not match the file path,
409 // the file is extracted with its memorized path.
410 // $p_path and $p_remove_path are commulative.
411 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
413 // Same as PclTarList()
414 // --------------------------------------------------------------------------------
415 function PclTarExtractList($p_tarname, $p_filelist, $p_path = "./", $p_remove_path = "", $p_mode = "") {
416 TrFctStart(__FILE__
, __LINE__
, "PclTarExtractList",
417 "tar=$p_tarname, list, path=$p_path, remove_path='$p_remove_path', mode='$p_mode'");
420 // ----- Extract the tar format from the extension
421 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
422 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
424 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
430 // ----- Look if the $p_filelist is really an array
431 if (is_array($p_filelist)) {
432 // ----- Call the extracting fct
433 if (($v_result = PclTarHandleExtract($p_tarname, $p_filelist, $p_list, "partial", $p_path, $p_mode,
434 $p_remove_path)) != 1
436 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
440 } // ----- Look if the $p_filelist is a string
442 if (is_string($p_filelist)) {
443 // ----- Create a list with the elements from the string
444 $v_list = explode(" ", $p_filelist);
446 // ----- Call the extracting fct
447 if (($v_result = PclTarHandleExtract($p_tarname, $v_list, $p_list, "partial", $p_path, $p_mode,
448 $p_remove_path)) != 1
450 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
454 } // ----- Invalid variable
457 PclErrorLog(-3, "Invalid variable type p_filelist");
460 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
467 TrFctEnd(__FILE__
, __LINE__
, $p_list);
472 // --------------------------------------------------------------------------------
474 // --------------------------------------------------------------------------------
475 // Function : PclTarExtractIndex()
477 // Extract the files present in the archive $p_tarname and specified at
478 // the indexes in $p_index, in the directory
479 // $p_path. The relative path of the archived files are keep and become
480 // relative to $p_path.
481 // If a directory is specified in the list, the directory only is created. All
482 // the file stored in this archive for this directory
483 // are not extracted.
484 // If a file with the same name already exists it will be replaced.
485 // If the path to the file does not exist, it will be created.
486 // Depending on the $p_tarname extension (.tar, .tar.gz or .tgz) the
487 // function will determine the type of the archive.
489 // $p_tarname : Name of an existing tar file
490 // $p_index : A single index (integer) or a string of indexes of files to
491 // extract. The form of the string is "0,4-6,8-12" with only numbers
492 // and '-' for range or ',' to separate ranges. No spaces or ';'
494 // $p_path : Path where the files will be extracted. The files will use
495 // their memorized path from $p_path.
496 // If $p_path is "", files will be extracted in "./".
497 // $p_remove_path : Path to remove (from the file memorized path) while writing the
498 // extracted files. If the path does not match the file path,
499 // the file is extracted with its memorized path.
500 // $p_path and $p_remove_path are commulative.
501 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
503 // Same as PclTarList()
504 // --------------------------------------------------------------------------------
505 function PclTarExtractIndex($p_tarname, $p_index, $p_path = "./", $p_remove_path = "", $p_mode = "") {
506 TrFctStart(__FILE__
, __LINE__
, "PclTarExtractIndex",
507 "tar=$p_tarname, index='$p_index', path=$p_path, remove_path='$p_remove_path', mode='$p_mode'");
510 // ----- Extract the tar format from the extension
511 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
512 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
514 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
520 // ----- Look if the $p_index is really an integer
521 if (is_integer($p_index)) {
522 // ----- Call the extracting fct
523 if (($v_result = PclTarHandleExtractByIndexList($p_tarname, "$p_index", $p_list, $p_path, $p_remove_path,
526 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
530 } // ----- Look if the $p_filelist is a string
532 if (is_string($p_index)) {
533 // ----- Call the extracting fct
534 if (($v_result = PclTarHandleExtractByIndexList($p_tarname, $p_index, $p_list, $p_path, $p_remove_path,
537 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
541 } // ----- Invalid variable
544 PclErrorLog(-3, "Invalid variable type $p_index");
547 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
554 TrFctEnd(__FILE__
, __LINE__
, $p_list);
559 // --------------------------------------------------------------------------------
561 // --------------------------------------------------------------------------------
562 // Function : PclTarDelete()
564 // This function deletes from the archive $p_tarname the files which are listed
565 // in $p_filelist. $p_filelist can be a string with file names separated by
566 // spaces, or an array containing the file names.
568 // $p_tarname : Name of an existing tar file
569 // $p_filelist : An array or a string containing file names to remove from the
571 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
573 // List of the files which are kept in the archive (same format as PclTarList())
574 // --------------------------------------------------------------------------------
575 function PclTarDelete($p_tarname, $p_filelist, $p_mode = "") {
576 TrFctStart(__FILE__
, __LINE__
, "PclTarDelete", "tar='$p_tarname', list='$p_filelist', mode='$p_mode'");
579 // ----- Extract the tar format from the extension
580 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
581 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
583 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
589 // ----- Look if the $p_filelist is really an array
590 if (is_array($p_filelist)) {
591 // ----- Call the extracting fct
592 if (($v_result = PclTarHandleDelete($p_tarname, $p_filelist, $p_list, $p_mode)) != 1) {
593 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
597 } // ----- Look if the $p_filelist is a string
599 if (is_string($p_filelist)) {
600 // ----- Create a list with the elements from the string
601 $v_list = explode(" ", $p_filelist);
603 // ----- Call the extracting fct
604 if (($v_result = PclTarHandleDelete($p_tarname, $v_list, $p_list, $p_mode)) != 1) {
605 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
609 } // ----- Invalid variable
612 PclErrorLog(-3, "Invalid variable type p_filelist");
615 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
622 TrFctEnd(__FILE__
, __LINE__
, $p_list);
627 // --------------------------------------------------------------------------------
629 // --------------------------------------------------------------------------------
630 // Function : PclTarUpdate()
632 // This function updates the files in $p_filelist which are already in the
633 // $p_tarname archive with an older last modified date. If the file does not
634 // exist, it is added at the end of the archive.
636 // $p_tarname : Name of an existing tar file
637 // $p_filelist : An array or a string containing file names to update from the
639 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
641 // List of the files contained in the archive. The field status contains
642 // "updated", "not_updated", "added" or "ok" for the files not concerned.
643 // --------------------------------------------------------------------------------
644 function PclTarUpdate($p_tarname, $p_filelist, $p_mode = "", $p_add_dir = "", $p_remove_dir = "") {
645 TrFctStart(__FILE__
, __LINE__
, "PclTarUpdate", "tar='$p_tarname', list='$p_filelist', mode='$p_mode'");
648 // ----- Extract the tar format from the extension
649 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
650 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
652 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
658 // ----- Look if the $p_filelist is really an array
659 if (is_array($p_filelist)) {
660 // ----- Call the extracting fct
661 if (($v_result = PclTarHandleUpdate($p_tarname, $p_filelist, $p_list, $p_mode, $p_add_dir, $p_remove_dir)) != 1) {
662 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
666 } // ----- Look if the $p_filelist is a string
668 if (is_string($p_filelist)) {
669 // ----- Create a list with the elements from the string
670 $v_list = explode(" ", $p_filelist);
672 // ----- Call the extracting fct
673 if (($v_result = PclTarHandleUpdate($p_tarname, $v_list, $p_list, $p_mode, $p_add_dir, $p_remove_dir)) != 1) {
674 TrFctEnd(__FILE__
, __LINE__
, 0, PclErrorString());
678 } // ----- Invalid variable
681 PclErrorLog(-3, "Invalid variable type p_filelist");
684 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
691 TrFctEnd(__FILE__
, __LINE__
, $p_list);
696 // --------------------------------------------------------------------------------
699 // --------------------------------------------------------------------------------
700 // Function : PclTarMerge()
702 // This function add the content of $p_tarname_add at the end of $p_tarname.
704 // $p_tarname : Name of an existing tar file
705 // $p_tarname_add : Name of an existing tar file taht will be added at the end
707 // $p_mode : 'tar' or 'tgz', if not set, will be determined by $p_tarname extension
708 // $p_mode_add : 'tar' or 'tgz', if not set, will be determined by $p_tarname_add
711 // List of the files contained in the archive. The field status contains
712 // "updated", "not_updated", "added" or "ok" for the files not concerned.
713 // --------------------------------------------------------------------------------
714 function PclTarMerge($p_tarname, $p_tarname_add, $p_mode = "", $p_mode_add = "") {
715 TrFctStart(__FILE__
, __LINE__
, "PclTarMerge",
716 "tar='$p_tarname', tar_add='$p_tarname_add', mode='$p_mode', mode_add='$p_mode_add'");
719 // ----- Check the parameters
720 if (($p_tarname == "") ||
($p_tarname_add == "")) {
722 PclErrorLog(-3, "Invalid empty archive name");
725 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
727 return PclErrorCode();
730 // ----- Extract the tar format from the extension
731 if (($p_mode == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
732 if (($p_mode = PclTarHandleExtension($p_tarname)) == "") {
734 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
739 if (($p_mode_add == "") ||
(($p_mode_add != "tar") && ($p_mode_add != "tgz"))) {
740 if (($p_mode_add = PclTarHandleExtension($p_tarname_add)) == "") {
742 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
748 // ----- Clear filecache
751 // ----- Check the file size
752 if ((!is_file($p_tarname)) ||
753 (((($v_size = filesize($p_tarname)) %
512) != 0) && ($p_mode == "tar"))
756 if (!is_file($p_tarname)) {
757 PclErrorLog(-4, "Archive '$p_tarname' does not exist");
759 PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . "(not a 512 block multiple)");
763 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
765 return PclErrorCode();
767 if ((!is_file($p_tarname_add)) ||
768 (((($v_size_add = filesize($p_tarname_add)) %
512) != 0) && ($p_mode_add == "tar"))
771 if (!is_file($p_tarname_add)) {
772 PclErrorLog(-4, "Archive '$p_tarname_add' does not exist");
775 "Archive '$p_tarname_add' has invalid size " . filesize($p_tarname_add) . "(not a 512 block multiple)");
779 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
781 return PclErrorCode();
784 // ----- Look for compressed archive
785 if ($p_mode == "tgz") {
786 // ----- Open the file in read mode
787 if (($p_tar = @gzopen
($p_tarname, "rb")) == 0) {
789 PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
792 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
794 return PclErrorCode();
797 // ----- Open a temporary file in write mode
798 $v_temp_tarname = uniqid("pcltar-") . ".tmp";
799 TrFctMessage(__FILE__
, __LINE__
, 2, "Creating temporary archive file $v_temp_tarname");
800 if (($v_temp_tar = @gzopen
($v_temp_tarname, "wb")) == 0) {
801 // ----- Close tar file
805 PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
808 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
810 return PclErrorCode();
813 // ----- Read the first 512 bytes block
814 $v_buffer = gzread($p_tar, 512);
816 // ----- Read the following blocks but not the last one
817 if (!gzeof($p_tar)) {
818 TrFctMessage(__FILE__
, __LINE__
, 3, "More than one 512 block file");
821 // ----- Read new 512 block and write the already read
823 // ----- Write the already read block
824 $v_binary_data = pack("a512", "$v_buffer");
825 gzputs($v_temp_tar, $v_binary_data);
828 TrFctMessage(__FILE__
, __LINE__
, 3, "Reading block $i");
830 // ----- Read next block
831 $v_buffer = gzread($p_tar, 512);
833 } while (!gzeof($p_tar));
835 TrFctMessage(__FILE__
, __LINE__
, 3, "$i 512 bytes blocks");
837 } // ----- Look for uncompressed tar file
839 if ($p_mode == "tar") {
840 // ----- Open the tar file
841 if (($p_tar = fopen($p_tarname, "r+b")) == 0) {
843 PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
846 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
848 return PclErrorCode();
851 // ----- Go to the beginning of last block
852 TrFctMessage(__FILE__
, __LINE__
, 4, "Position before :" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
853 fseek($p_tar, $v_size - 512);
854 TrFctMessage(__FILE__
, __LINE__
, 4, "Position after :" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
855 } // ----- Look for unknown type
858 PclErrorLog(-3, "Invalid tar mode $p_mode");
861 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
863 return PclErrorCode();
867 // ----- Look for type of archive to add
868 if ($p_mode_add == "tgz") {
869 TrFctMessage(__FILE__
, __LINE__
, 4, "Opening file $p_tarname_add");
871 // ----- Open the file in read mode
872 if (($p_tar_add = @gzopen
($p_tarname_add, "rb")) == 0) {
874 PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
877 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
879 return PclErrorCode();
882 // ----- Read the first 512 bytes block
883 $v_buffer = gzread($p_tar_add, 512);
885 // ----- Read the following blocks but not the last one
886 if (!gzeof($p_tar_add)) {
887 TrFctMessage(__FILE__
, __LINE__
, 3, "More than one 512 block file");
890 // ----- Read new 512 block and write the already read
892 // ----- Write the already read block
893 $v_binary_data = pack("a512", "$v_buffer");
894 if ($p_mode == "tar") {
895 fputs($p_tar, $v_binary_data);
897 gzputs($v_temp_tar, $v_binary_data);
901 TrFctMessage(__FILE__
, __LINE__
, 3, "Reading block $i");
903 // ----- Read next block
904 $v_buffer = gzread($p_tar_add, 512);
906 } while (!gzeof($p_tar_add));
908 TrFctMessage(__FILE__
, __LINE__
, 3, "$i 512 bytes blocks");
911 // ----- Close the files
913 } // ----- Look for uncompressed tar file
915 if ($p_mode == "tar") {
916 // ----- Open the file in read mode
917 if (($p_tar_add = @fopen
($p_tarname_add, "rb")) == 0) {
919 PclErrorLog(-2, "Unable to open file '$p_tarname_add' in binary read mode");
922 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
924 return PclErrorCode();
927 // ----- Read the first 512 bytes block
928 $v_buffer = fread($p_tar_add, 512);
930 // ----- Read the following blocks but not the last one
931 if (!feof($p_tar_add)) {
932 TrFctMessage(__FILE__
, __LINE__
, 3, "More than one 512 block file");
935 // ----- Read new 512 block and write the already read
937 // ----- Write the already read block
938 $v_binary_data = pack("a512", "$v_buffer");
939 if ($p_mode == "tar") {
940 fputs($p_tar, $v_binary_data);
942 gzputs($v_temp_tar, $v_binary_data);
946 TrFctMessage(__FILE__
, __LINE__
, 3, "Reading block $i");
948 // ----- Read next block
949 $v_buffer = fread($p_tar_add, 512);
951 } while (!feof($p_tar_add));
953 TrFctMessage(__FILE__
, __LINE__
, 3, "$i 512 bytes blocks");
956 // ----- Close the files
961 // ----- Call the footer of the tar archive
962 $v_result = PclTarHandleFooter($p_tar, $p_mode);
964 // ----- Look for closing compressed archive
965 if ($p_mode == "tgz") {
966 // ----- Close the files
968 gzclose($v_temp_tar);
970 // ----- Unlink tar file
971 if (!@unlink
($p_tarname)) {
973 PclErrorLog(-11, "Error while deleting archive name $p_tarname");
976 // ----- Rename tar file
977 if (!@rename
($v_temp_tarname, $p_tarname)) {
979 PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
982 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
984 return PclErrorCode();
988 TrFctEnd(__FILE__
, __LINE__
, $v_result);
991 } // ----- Look for closing uncompressed tar file
993 if ($p_mode == "tar") {
994 // ----- Close the tarfile
1000 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1005 // --------------------------------------------------------------------------------
1008 // --------------------------------------------------------------------------------
1009 // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1011 // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1012 // --------------------------------------------------------------------------------
1015 // --------------------------------------------------------------------------------
1016 // Function : PclTarHandleCreate()
1019 // $p_tarname : Name of the tar file
1020 // $p_list : An array containing the file or directory names to add in the tar
1021 // $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1023 // --------------------------------------------------------------------------------
1024 function PclTarHandleCreate($p_tarname, $p_list, $p_mode, $p_add_dir = "", $p_remove_dir = "") {
1025 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleCreate",
1026 "tar=$p_tarname, list, mode=$p_mode, add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1028 $v_list_detail = array();
1030 // ----- Check the parameters
1031 if (($p_tarname == "") ||
(($p_mode != "tar") && ($p_mode != "tgz"))) {
1033 if ($p_tarname == "") {
1034 PclErrorLog(-3, "Invalid empty archive name");
1036 PclErrorLog(-3, "Unknown mode '$p_mode'");
1040 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1042 return PclErrorCode();
1045 // ----- Look for tar file
1046 if ($p_mode == "tar") {
1047 // ----- Open the tar file
1048 if (($p_tar = fopen($p_tarname, "wb")) == 0) {
1050 PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1053 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1055 return PclErrorCode();
1058 // ----- Call the adding fct inside the tar
1059 if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1060 // ----- Call the footer of the tar archive
1061 $v_result = PclTarHandleFooter($p_tar, $p_mode);
1064 // ----- Close the tarfile
1066 } // ----- Look for tgz file
1068 // ----- Open the tar file
1069 if (($p_tar = @gzopen
($p_tarname, "wb")) == 0) {
1071 PclErrorLog(-1, "Unable to open file [$p_tarname] in binary write mode");
1074 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1076 return PclErrorCode();
1079 // ----- Call the adding fct inside the tar
1080 if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1) {
1081 // ----- Call the footer of the tar archive
1082 $v_result = PclTarHandleFooter($p_tar, $p_mode);
1085 // ----- Close the tarfile
1090 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1095 // --------------------------------------------------------------------------------
1097 // --------------------------------------------------------------------------------
1098 // Function : PclTarHandleAppend()
1101 // $p_tarname : Name of the tar file
1102 // $p_list : An array containing the file or directory names to add in the tar
1103 // $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1105 // --------------------------------------------------------------------------------
1106 function PclTarHandleAppend($p_tarname, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir) {
1107 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleAppend", "tar=$p_tarname, list, mode=$p_mode");
1110 // ----- Check the parameters
1111 if ($p_tarname == "") {
1113 PclErrorLog(-3, "Invalid empty archive name");
1116 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1118 return PclErrorCode();
1123 // ----- Check the file size
1124 if ((!is_file($p_tarname)) ||
1125 (((($v_size = filesize($p_tarname)) %
512) != 0) && ($p_mode == "tar"))
1128 if (!is_file($p_tarname)) {
1129 PclErrorLog(-4, "Archive '$p_tarname' does not exist");
1131 PclErrorLog(-6, "Archive '$p_tarname' has invalid size " . filesize($p_tarname) . "(not a 512 block multiple)");
1135 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1137 return PclErrorCode();
1140 // ----- Look for compressed archive
1141 if ($p_mode == "tgz") {
1142 // ----- Open the file in read mode
1143 if (($p_tar = @gzopen
($p_tarname, "rb")) == 0) {
1145 PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
1148 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1150 return PclErrorCode();
1153 // ----- Open a temporary file in write mode
1154 $v_temp_tarname = uniqid("pcltar-") . ".tmp";
1155 TrFctMessage(__FILE__
, __LINE__
, 2, "Creating temporary archive file $v_temp_tarname");
1156 if (($v_temp_tar = @gzopen
($v_temp_tarname, "wb")) == 0) {
1157 // ----- Close tar file
1161 PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
1164 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1166 return PclErrorCode();
1169 // ----- Read the first 512 bytes block
1170 $v_buffer = gzread($p_tar, 512);
1172 // ----- Read the following blocks but not the last one
1173 if (!gzeof($p_tar)) {
1174 TrFctMessage(__FILE__
, __LINE__
, 3, "More than one 512 block file");
1177 // ----- Read new 512 block and write the already read
1179 // ----- Write the already read block
1180 $v_binary_data = pack("a512", "$v_buffer");
1181 gzputs($v_temp_tar, $v_binary_data);
1184 TrFctMessage(__FILE__
, __LINE__
, 3, "Reading block $i");
1186 // ----- Read next block
1187 $v_buffer = gzread($p_tar, 512);
1189 } while (!gzeof($p_tar));
1191 TrFctMessage(__FILE__
, __LINE__
, 3, "$i 512 bytes blocks");
1194 // ----- Call the adding fct inside the tar
1195 if (($v_result = PclTarHandleAddList($v_temp_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir,
1196 $p_remove_dir)) == 1
1198 // ----- Call the footer of the tar archive
1199 $v_result = PclTarHandleFooter($v_temp_tar, $p_mode);
1202 // ----- Close the files
1204 gzclose($v_temp_tar);
1206 // ----- Unlink tar file
1207 if (!@unlink
($p_tarname)) {
1209 PclErrorLog(-11, "Error while deleting archive name $p_tarname");
1212 // ----- Rename tar file
1213 if (!@rename
($v_temp_tarname, $p_tarname)) {
1215 PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
1218 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1220 return PclErrorCode();
1224 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1227 } // ----- Look for uncompressed tar file
1229 if ($p_mode == "tar") {
1230 // ----- Open the tar file
1231 if (($p_tar = fopen($p_tarname, "r+b")) == 0) {
1233 PclErrorLog(-1, "Unable to open file '$p_tarname' in binary write mode");
1236 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1238 return PclErrorCode();
1241 // ----- Go to the beginning of last block
1242 TrFctMessage(__FILE__
, __LINE__
, 4, "Position before :" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1243 fseek($p_tar, $v_size - 512);
1244 TrFctMessage(__FILE__
, __LINE__
, 4, "Position after :" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1246 // ----- Call the adding fct inside the tar
1247 if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir,
1248 $p_remove_dir)) == 1
1250 // ----- Call the footer of the tar archive
1251 $v_result = PclTarHandleFooter($p_tar, $p_mode);
1254 // ----- Close the tarfile
1256 } // ----- Look for unknown type
1259 PclErrorLog(-3, "Invalid tar mode $p_mode");
1262 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1264 return PclErrorCode();
1269 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1274 // --------------------------------------------------------------------------------
1276 // --------------------------------------------------------------------------------
1277 // Function : PclTarHandleAddList()
1279 // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
1280 // different from the real path of the file. This is usefull if you want to have PclTar
1281 // running in any directory, and memorize relative path from an other directory.
1283 // $p_tar : File descriptor of the tar archive
1284 // $p_list : An array containing the file or directory names to add in the tar
1285 // $p_mode : "tar" for normal tar archive, "tgz" for gzipped tar archive
1286 // $p_list_detail : list of added files with their properties (specially the status field)
1287 // $p_add_dir : Path to add in the filename path archived
1288 // $p_remove_dir : Path to remove in the filename path archived
1290 // --------------------------------------------------------------------------------
1291 function PclTarHandleAddList($p_tar, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir) {
1292 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleAddList",
1293 "tar='$p_tar', list, mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1295 $v_header = array();
1297 // ----- Recuperate the current number of elt in list
1298 $v_nb = sizeof($p_list_detail);
1300 // ----- Check the parameters
1303 PclErrorLog(-3, "Invalid file descriptor in file " . __FILE__
. ", line " . __LINE__
);
1306 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1308 return PclErrorCode();
1311 // ----- Check the arguments
1312 if (sizeof($p_list) == 0) {
1314 PclErrorLog(-3, "Invalid file list parameter (invalid or empty list)");
1317 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1319 return PclErrorCode();
1322 // ----- Loop on the files
1323 for ($j = 0; ($j < count($p_list)) && ($v_result == 1); $j++
) {
1324 // ----- Recuperate the filename
1325 $p_filename = $p_list[$j];
1327 TrFctMessage(__FILE__
, __LINE__
, 2, "Looking for file [$p_filename]");
1329 // ----- Skip empty file names
1330 if ($p_filename == "") {
1331 TrFctMessage(__FILE__
, __LINE__
, 2, "Skip empty filename");
1335 // ----- Check the filename
1336 if (!file_exists($p_filename)) {
1338 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$p_filename' does not exists");
1339 PclErrorLog(-4, "File '$p_filename' does not exists");
1342 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1344 return PclErrorCode();
1347 // ----- Check the path length
1348 if (strlen($p_filename) > 99) {
1350 PclErrorLog(-5, "File name is too long (max. 99) : '$p_filename'");
1353 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1355 return PclErrorCode();
1358 TrFctMessage(__FILE__
, __LINE__
, 4,
1359 "File position before header =" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1361 // ----- Add the file
1362 if (($v_result = PclTarHandleAddFile($p_tar, $p_filename, $p_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1) {
1363 // ----- Return status
1364 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1369 // ----- Store the file infos
1370 $p_list_detail[$v_nb++
] = $v_header;
1372 // ----- Look for directory
1373 if (is_dir($p_filename)) {
1374 TrFctMessage(__FILE__
, __LINE__
, 2, "$p_filename is a directory");
1376 // ----- Look for path
1377 if ($p_filename != ".") {
1378 $v_path = $p_filename . "/";
1383 // ----- Read the directory for files and sub-directories
1384 $p_hdir = opendir($p_filename);
1385 $p_hitem = readdir($p_hdir); // '.' directory
1386 $p_hitem = readdir($p_hdir); // '..' directory
1387 while ($p_hitem = readdir($p_hdir)) {
1388 // ----- Look for a file
1389 if (is_file($v_path . $p_hitem)) {
1390 TrFctMessage(__FILE__
, __LINE__
, 4, "Add the file '" . $v_path . $p_hitem . "'");
1392 // ----- Add the file
1393 if (($v_result = PclTarHandleAddFile($p_tar, $v_path . $p_hitem, $p_mode, $v_header, $p_add_dir,
1394 $p_remove_dir)) != 1
1396 // ----- Return status
1397 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1402 // ----- Store the file infos
1403 $p_list_detail[$v_nb++
] = $v_header;
1404 } // ----- Recursive call to PclTarHandleAddFile()
1406 TrFctMessage(__FILE__
, __LINE__
, 4, "'" . $v_path . $p_hitem . "' is a directory");
1408 // ----- Need an array as parameter
1409 $p_temp_list[0] = $v_path . $p_hitem;
1410 $v_result = PclTarHandleAddList($p_tar, $p_temp_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
1414 // ----- Free memory for the recursive loop
1415 unset($p_temp_list);
1419 TrFctMessage(__FILE__
, __LINE__
, 4,
1420 "File position after blocks =" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1425 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1430 // --------------------------------------------------------------------------------
1432 // --------------------------------------------------------------------------------
1433 // Function : PclTarHandleAddFile()
1437 // --------------------------------------------------------------------------------
1438 function PclTarHandleAddFile($p_tar, $p_filename, $p_mode, &$p_header, $p_add_dir, $p_remove_dir) {
1439 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleAddFile",
1440 "tar='$p_tar', filename='$p_filename', p_mode='$p_mode', add_dir='$p_add_dir', remove_dir='$p_remove_dir'");
1443 // ----- Check the parameters
1446 PclErrorLog(-3, "Invalid file descriptor in file " . __FILE__
. ", line " . __LINE__
);
1449 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1451 return PclErrorCode();
1454 // ----- Skip empty file names
1455 if ($p_filename == "") {
1457 PclErrorLog(-3, "Invalid file list parameter (invalid or empty list)");
1460 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1462 return PclErrorCode();
1465 // ----- Calculate the stored filename
1466 $v_stored_filename = $p_filename;
1467 if ($p_remove_dir != "") {
1468 if (substr($p_remove_dir, -1) != '/') {
1469 $p_remove_dir .= "/";
1472 if ((substr($p_filename, 0, 2) == "./") ||
(substr($p_remove_dir, 0, 2) == "./")) {
1473 if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./")) {
1474 $p_remove_dir = "./" . $p_remove_dir;
1476 if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./")) {
1477 $p_remove_dir = substr($p_remove_dir, 2);
1481 if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) {
1482 $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
1483 TrFctMessage(__FILE__
, __LINE__
, 3, "Remove path '$p_remove_dir' in file '$p_filename' = '$v_stored_filename'");
1486 if ($p_add_dir != "") {
1487 if (substr($p_add_dir, -1) == "/") {
1488 $v_stored_filename = $p_add_dir . $v_stored_filename;
1490 $v_stored_filename = $p_add_dir . "/" . $v_stored_filename;
1492 TrFctMessage(__FILE__
, __LINE__
, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
1495 // ----- Check the path length
1496 if (strlen($v_stored_filename) > 99) {
1498 PclErrorLog(-5, "Stored file name is too long (max. 99) : '$v_stored_filename'");
1501 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1503 return PclErrorCode();
1506 // ----- Look for a file
1507 if (is_file($p_filename)) {
1508 // ----- Open the source file
1509 if (($v_file = fopen($p_filename, "rb")) == 0) {
1511 PclErrorLog(-2, "Unable to open file '$p_filename' in binary read mode");
1514 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1516 return PclErrorCode();
1519 // ----- Call the header generation
1520 if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1) {
1521 // ----- Return status
1522 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1527 TrFctMessage(__FILE__
, __LINE__
, 4,
1528 "File position after header =" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1530 // ----- Read the file by 512 octets blocks
1532 while (($v_buffer = fread($v_file, 512)) != "") {
1533 $v_binary_data = pack("a512", "$v_buffer");
1534 if ($p_mode == "tar") {
1535 fputs($p_tar, $v_binary_data);
1537 gzputs($p_tar, $v_binary_data);
1541 TrFctMessage(__FILE__
, __LINE__
, 2, "$i 512 bytes blocks");
1543 // ----- Close the file
1546 TrFctMessage(__FILE__
, __LINE__
, 4,
1547 "File position after blocks =" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1548 } // ----- Look for a directory
1550 // ----- Call the header generation
1551 if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1) {
1552 // ----- Return status
1553 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1558 TrFctMessage(__FILE__
, __LINE__
, 4,
1559 "File position after header =" . ($p_mode == "tar" ?
ftell($p_tar) : gztell($p_tar)));
1563 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1568 // --------------------------------------------------------------------------------
1570 // --------------------------------------------------------------------------------
1571 // Function : PclTarHandleHeader()
1573 // This function creates in the TAR $p_tar, the TAR header for the file
1576 // 1. The informations needed to compose the header are recuperated and formatted
1577 // 2. Two binary strings are composed for the first part of the header, before
1578 // and after checksum field.
1579 // 3. The checksum is calculated from the two binary strings
1580 // 4. The header is write in the tar file (first binary string, binary string
1581 // for checksum and last binary string).
1583 // $p_tar : a valid file descriptor, opened in write mode,
1584 // $p_filename : The name of the file the header is for,
1585 // $p_mode : The mode of the archive ("tar" or "tgz").
1586 // $p_header : A pointer to a array where will be set the file properties
1588 // --------------------------------------------------------------------------------
1589 function PclTarHandleHeader($p_tar, $p_filename, $p_mode, &$p_header, $p_stored_filename) {
1590 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleHeader",
1591 "tar=$p_tar, file='$p_filename', mode='$p_mode', stored_filename='$p_stored_filename'");
1594 // ----- Check the parameters
1595 if (($p_tar == 0) ||
($p_filename == "")) {
1597 PclErrorLog(-3, "Invalid file descriptor in file " . __FILE__
. ", line " . __LINE__
);
1600 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1602 return PclErrorCode();
1605 // ----- Filename (reduce the path of stored name)
1606 if ($p_stored_filename == "") {
1607 $p_stored_filename = $p_filename;
1609 $v_reduce_filename = PclTarHandlePathReduction($p_stored_filename);
1610 TrFctMessage(__FILE__
, __LINE__
, 2,
1611 "Filename (reduced) '$v_reduce_filename', strlen " . strlen($v_reduce_filename));
1613 // ----- Get file info
1614 $v_info = stat($p_filename);
1615 $v_uid = sprintf("%6s ", DecOct($v_info[4]));
1616 $v_gid = sprintf("%6s ", DecOct($v_info[5]));
1617 TrFctMessage(__FILE__
, __LINE__
, 3, "uid=$v_uid, gid=$v_gid");
1618 $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename)));
1619 TrFctMessage(__FILE__
, __LINE__
, 3, "file permissions $v_perms");
1622 $v_mtime_data = filemtime($p_filename);
1623 TrFctMessage(__FILE__
, __LINE__
, 2, "File mtime : $v_mtime_data");
1624 $v_mtime = sprintf("%11s", DecOct($v_mtime_data));
1626 // ----- File typeflag
1627 // '0' or '\0' is the code for regular file
1629 if (is_dir($p_filename)) {
1635 // ----- Get the file size
1637 $v_size = filesize($p_filename);
1640 TrFctMessage(__FILE__
, __LINE__
, 2, "File size : $v_size");
1641 $v_size = sprintf("%11s ", DecOct($v_size));
1643 TrFctMessage(__FILE__
, __LINE__
, 2, "File typeflag : $v_typeflag");
1669 // ----- Compose the binary string of the header in two parts arround the checksum position
1670 $v_binary_data_first = pack("a100a8a8a8a12A12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
1671 $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname,
1672 $v_gname, $v_devmajor, $v_devminor, $v_prefix, "");
1674 // ----- Calculate the checksum
1676 // ..... First part of the header
1677 for ($i = 0; $i < 148; $i++
) {
1678 $v_checksum +
= ord(substr($v_binary_data_first, $i, 1));
1680 // ..... Ignore the checksum value and replace it by ' ' (space)
1681 for ($i = 148; $i < 156; $i++
) {
1682 $v_checksum +
= ord(' ');
1684 // ..... Last part of the header
1685 for ($i = 156, $j = 0; $i < 512; $i++
, $j++
) {
1686 $v_checksum +
= ord(substr($v_binary_data_last, $j, 1));
1688 TrFctMessage(__FILE__
, __LINE__
, 3, "Calculated checksum : $v_checksum");
1690 // ----- Write the first 148 bytes of the header in the archive
1691 if ($p_mode == "tar") {
1692 fputs($p_tar, $v_binary_data_first, 148);
1694 gzputs($p_tar, $v_binary_data_first, 148);
1697 // ----- Write the calculated checksum
1698 $v_checksum = sprintf("%6s ", DecOct($v_checksum));
1699 $v_binary_data = pack("a8", $v_checksum);
1700 if ($p_mode == "tar") {
1701 fputs($p_tar, $v_binary_data, 8);
1703 gzputs($p_tar, $v_binary_data, 8);
1706 // ----- Write the last 356 bytes of the header in the archive
1707 if ($p_mode == "tar") {
1708 fputs($p_tar, $v_binary_data_last, 356);
1710 gzputs($p_tar, $v_binary_data_last, 356);
1713 // ----- Set the properties in the header "structure"
1714 $p_header['filename'] = $v_reduce_filename;
1715 $p_header['mode'] = $v_perms;
1716 $p_header['uid'] = $v_uid;
1717 $p_header['gid'] = $v_gid;
1718 $p_header['size'] = $v_size;
1719 $p_header['mtime'] = $v_mtime;
1720 $p_header['typeflag'] = $v_typeflag;
1721 $p_header['status'] = "added";
1724 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1729 // --------------------------------------------------------------------------------
1731 // --------------------------------------------------------------------------------
1732 // Function : PclTarHandleFooter()
1736 // --------------------------------------------------------------------------------
1737 function PclTarHandleFooter($p_tar, $p_mode) {
1738 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleFooter", "tar='$p_tar', p_mode=$p_mode");
1741 // ----- Write the last 0 filled block for end of archive
1742 $v_binary_data = pack("a512", "");
1743 if ($p_mode == "tar") {
1744 fputs($p_tar, $v_binary_data);
1746 gzputs($p_tar, $v_binary_data);
1750 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1755 // --------------------------------------------------------------------------------
1757 // --------------------------------------------------------------------------------
1758 // Function : PclTarHandleExtract()
1761 // $p_tarname : Filename of the tar (or tgz) archive
1762 // $p_file_list : An array which contains the list of files to extract, this
1763 // array may be empty when $p_mode is 'complete'
1764 // $p_list_detail : An array where will be placed the properties of each extracted/listed file
1765 // $p_mode : 'complete' will extract all files from the archive,
1766 // 'partial' will look for files in $p_file_list
1767 // 'list' will only list the files from the archive without any extract
1768 // $p_path : Path to add while writing the extracted files
1769 // $p_tar_mode : 'tar' for GNU TAR archive, 'tgz' for compressed archive
1770 // $p_remove_path : Path to remove (from the file memorized path) while writing the
1771 // extracted files. If the path does not match the file path,
1772 // the file is extracted with its memorized path.
1773 // $p_remove_path does not apply to 'list' mode.
1774 // $p_path and $p_remove_path are commulative.
1776 // --------------------------------------------------------------------------------
1777 function PclTarHandleExtract(
1786 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleExtract",
1787 "archive='$p_tarname', list, mode=$p_mode, path=$p_path, tar_mode=$p_tar_mode, remove_path='$p_remove_path'");
1790 $v_extract_all = true;
1793 // ----- Check the path
1794 if (($p_path == "") ||
((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../"))) {
1795 $p_path = "./" . $p_path;
1798 // ----- Look for path to remove format (should end by /)
1799 if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
1800 $p_remove_path .= '/';
1802 $p_remove_path_size = strlen($p_remove_path);
1804 // ----- Study the mode
1807 // ----- Flag extract of all files
1808 $v_extract_all = true;
1812 // ----- Flag extract of specific files
1813 $v_extract_all = false;
1817 // ----- Flag list of all files
1818 $v_extract_all = false;
1823 PclErrorLog(-3, "Invalid extract mode ($p_mode)");
1826 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1828 return PclErrorCode();
1831 // ----- Open the tar file
1832 if ($p_tar_mode == "tar") {
1833 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in binary read mode");
1834 $v_tar = fopen($p_tarname, "rb");
1836 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in gzip binary read mode");
1837 $v_tar = @gzopen
($p_tarname, "rb");
1840 // ----- Check that the archive is open
1843 PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
1846 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
1848 return PclErrorCode();
1851 // ----- Read the blocks
1852 while (!($v_end_of_file = ($p_tar_mode == "tar" ?
feof($v_tar) : gzeof($v_tar)))) {
1853 TrFctMessage(__FILE__
, __LINE__
, 3, "Looking for next header ...");
1855 // ----- Clear cache of file infos
1858 // ----- Reset extract tag
1859 $v_extract_file = false;
1860 $v_extraction_stopped = 0;
1862 // ----- Read the 512 bytes header
1863 if ($p_tar_mode == "tar") {
1864 $v_binary_data = fread($v_tar, 512);
1866 $v_binary_data = gzread($v_tar, 512);
1869 // ----- Read the header properties
1870 if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
1871 // ----- Close the archive file
1872 if ($p_tar_mode == "tar") {
1879 TrFctEnd(__FILE__
, __LINE__
, $v_result);
1884 // ----- Look for empty blocks to skip
1885 if ($v_header['filename'] == "") {
1886 TrFctMessage(__FILE__
, __LINE__
, 2, "Empty block found. End of archive ?");
1890 TrFctMessage(__FILE__
, __LINE__
, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
1892 // ----- Look for partial extract
1893 if ((!$v_extract_all) && (is_array($p_file_list))) {
1894 TrFctMessage(__FILE__
, __LINE__
, 2, "Look if the file '$v_header[filename]' need to be extracted");
1896 // ----- By default no unzip if the file is not found
1897 $v_extract_file = false;
1899 // ----- Look into the file list
1900 for ($i = 0; $i < sizeof($p_file_list); $i++
) {
1901 TrFctMessage(__FILE__
, __LINE__
, 2,
1902 "Compare archived file '$v_header[filename]' from asked list file '" . $p_file_list[$i] . "'");
1904 // ----- Look if it is a directory
1905 if (substr($p_file_list[$i], -1) == "/") {
1906 TrFctMessage(__FILE__
, __LINE__
, 3, "Compare file '$v_header[filename]' with directory '$p_file_list[$i]'");
1908 // ----- Look if the directory is in the filename path
1909 if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0,
1910 strlen($p_file_list[$i])) == $p_file_list[$i])
1912 // ----- The file is in the directory, so extract it
1913 TrFctMessage(__FILE__
, __LINE__
, 2,
1914 "File '$v_header[filename]' is in directory '$p_file_list[$i]' : extract it");
1915 $v_extract_file = true;
1917 // ----- End of loop
1920 } // ----- It is a file, so compare the file names
1922 if ($p_file_list[$i] == $v_header['filename']) {
1924 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$v_header[filename]' should be extracted");
1925 $v_extract_file = true;
1927 // ----- End of loop
1934 if (!$v_extract_file) {
1935 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$v_header[filename]' should not be extracted");
1938 // ----- All files need to be extracted
1939 $v_extract_file = true;
1942 // ----- Look if this file need to be extracted
1943 if (($v_extract_file) && (!$v_listing)) {
1944 // ----- Look for path to remove
1945 if (($p_remove_path != "")
1946 && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)
1948 TrFctMessage(__FILE__
, __LINE__
, 3, "Found path '$p_remove_path' to remove in file '$v_header[filename]'");
1949 // ----- Remove the path
1950 $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
1951 TrFctMessage(__FILE__
, __LINE__
, 3, "Reslting file is '$v_header[filename]'");
1954 // ----- Add the path to the file
1955 if (($p_path != "./") && ($p_path != "/")) {
1956 // ----- Look for the path end '/'
1957 while (substr($p_path, -1) == "/") {
1958 TrFctMessage(__FILE__
, __LINE__
, 3, "Destination path [$p_path] ends by '/'");
1959 $p_path = substr($p_path, 0, strlen($p_path) - 1);
1960 TrFctMessage(__FILE__
, __LINE__
, 3, "Modified to [$p_path]");
1963 // ----- Add the path
1964 if (substr($v_header['filename'], 0, 1) == "/") {
1965 $v_header['filename'] = $p_path . $v_header['filename'];
1967 $v_header['filename'] = $p_path . "/" . $v_header['filename'];
1972 TrFctMessage(__FILE__
, __LINE__
, 2,
1973 "Extracting file (with path) '$v_header[filename]', size '$v_header[size]'");
1975 // ----- Check that the file does not exists
1976 if (file_exists($v_header['filename'])) {
1977 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$v_header[filename]' already exists");
1979 // ----- Look if file is a directory
1980 if (is_dir($v_header['filename'])) {
1981 TrFctMessage(__FILE__
, __LINE__
, 2, "Existing file '$v_header[filename]' is a directory");
1983 // ----- Change the file status
1984 $v_header['status'] = "already_a_directory";
1986 // ----- Skip the extract
1987 $v_extraction_stopped = 1;
1988 $v_extract_file = 0;
1989 } // ----- Look if file is write protected
1991 if (!is_writeable($v_header['filename'])) {
1992 TrFctMessage(__FILE__
, __LINE__
, 2, "Existing file '$v_header[filename]' is write protected");
1994 // ----- Change the file status
1995 $v_header['status'] = "write_protected";
1997 // ----- Skip the extract
1998 $v_extraction_stopped = 1;
1999 $v_extract_file = 0;
2000 } // ----- Look if the extracted file is older
2002 if (filemtime($v_header['filename']) > $v_header['mtime']) {
2003 TrFctMessage(__FILE__
, __LINE__
, 2,
2004 "Existing file '$v_header[filename]' is newer (" . date("l dS of F Y h:i:s A",
2005 filemtime($v_header['filename'])) . ") than the extracted file (" . date("l dS of F Y h:i:s A",
2006 $v_header['mtime']) . ")");
2008 // ----- Change the file status
2009 $v_header['status'] = "newer_exist";
2011 // ----- Skip the extract
2012 $v_extraction_stopped = 1;
2013 $v_extract_file = 0;
2017 } // ----- Check the directory availability and create it if necessary
2019 if ($v_header['typeflag'] == "5") {
2020 $v_dir_to_check = $v_header['filename'];
2022 if (!strstr($v_header['filename'], "/")) {
2023 $v_dir_to_check = "";
2025 $v_dir_to_check = dirname($v_header['filename']);
2029 if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1) {
2030 TrFctMessage(__FILE__
, __LINE__
, 2, "Unable to create path for '$v_header[filename]'");
2032 // ----- Change the file status
2033 $v_header['status'] = "path_creation_fail";
2035 // ----- Skip the extract
2036 $v_extraction_stopped = 1;
2037 $v_extract_file = 0;
2041 // ----- Do the extraction
2042 if (($v_extract_file) && ($v_header['typeflag'] != "5")) {
2043 // ----- Open the destination file in write mode
2044 if (($v_dest_file = @fopen
($v_header['filename'], "wb")) == 0) {
2045 TrFctMessage(__FILE__
, __LINE__
, 2, "Error while opening '$v_header[filename]' in write binary mode");
2047 // ----- Change the file status
2048 $v_header['status'] = "write_error";
2050 // ----- Jump to next file
2051 TrFctMessage(__FILE__
, __LINE__
, 2, "Jump to next file");
2052 if ($p_tar_mode == "tar") {
2053 fseek($v_tar, ftell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2055 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2058 TrFctMessage(__FILE__
, __LINE__
, 2, "Start extraction of '$v_header[filename]'");
2061 $n = floor($v_header['size'] / 512);
2062 for ($i = 0; $i < $n; $i++
) {
2063 TrFctMessage(__FILE__
, __LINE__
, 3, "Read complete 512 bytes block number " . ($i +
1));
2064 if ($p_tar_mode == "tar") {
2065 $v_content = fread($v_tar, 512);
2067 $v_content = gzread($v_tar, 512);
2069 fwrite($v_dest_file, $v_content, 512);
2071 if (($v_header['size'] %
512) != 0) {
2072 TrFctMessage(__FILE__
, __LINE__
, 3, "Read last " . ($v_header['size'] %
512) . " bytes in a 512 block");
2073 if ($p_tar_mode == "tar") {
2074 $v_content = fread($v_tar, 512);
2076 $v_content = gzread($v_tar, 512);
2078 fwrite($v_dest_file, $v_content, ($v_header['size'] %
512));
2081 // ----- Close the destination file
2082 fclose($v_dest_file);
2084 // ----- Change the file mode, mtime
2085 touch($v_header['filename'], $v_header['mtime']);
2086 //chmod($v_header['filename'], DecOct($v_header['mode']));
2089 // ----- Check the file size
2091 if (filesize($v_header['filename']) != $v_header['size']) {
2092 // ----- Close the archive file
2093 if ($p_tar_mode == "tar") {
2101 "Extracted file '$v_header[filename]' does not have the correct file size '" . filesize($v_filename) . "' ('$v_header[size]' expected). Archive may be corrupted.");
2104 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2106 return PclErrorCode();
2110 TrFctMessage(__FILE__
, __LINE__
, 2, "Extraction done");
2112 TrFctMessage(__FILE__
, __LINE__
, 2, "Extraction of file '$v_header[filename]' skipped.");
2114 // ----- Jump to next file
2115 TrFctMessage(__FILE__
, __LINE__
, 2, "Jump to next file");
2116 if ($p_tar_mode == "tar") {
2117 fseek($v_tar, ftell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2119 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2122 } // ----- Look for file that is not to be unzipped
2125 TrFctMessage(__FILE__
, __LINE__
, 2, "Jump file '$v_header[filename]'");
2126 TrFctMessage(__FILE__
, __LINE__
, 4,
2127 "Position avant jump [" . ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) . "]");
2129 // ----- Jump to next file
2130 if ($p_tar_mode == "tar") {
2131 fseek($v_tar, ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) +
(ceil(($v_header['size'] / 512)) * 512));
2133 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2136 TrFctMessage(__FILE__
, __LINE__
, 4,
2137 "Position apr�s jump [" . ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) . "]");
2140 if ($p_tar_mode == "tar") {
2141 $v_end_of_file = feof($v_tar);
2143 $v_end_of_file = gzeof($v_tar);
2146 // ----- File name and properties are logged if listing mode or file is extracted
2147 if ($v_listing ||
$v_extract_file ||
$v_extraction_stopped) {
2148 TrFctMessage(__FILE__
, __LINE__
, 2, "Memorize info about file '$v_header[filename]'");
2150 // ----- Log extracted files
2151 if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2154 if ((substr($v_header['filename'], 0, 1) == "/") && ($v_file_dir == "")) {
2158 // ----- Add the array describing the file into the list
2159 $p_list_detail[$v_nb] = $v_header;
2166 // ----- Close the tarfile
2167 if ($p_tar_mode == "tar") {
2174 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2179 // --------------------------------------------------------------------------------
2181 // --------------------------------------------------------------------------------
2182 // Function : PclTarHandleExtractByIndexList()
2184 // Extract the files which are at the indexes specified. If the 'file' at the
2185 // index is a directory, the directory only is created, not all the files stored
2186 // for that directory.
2188 // $p_index_string : String of indexes of files to extract. The form of the
2189 // string is "0,4-6,8-12" with only numbers and '-' for
2190 // for range, and ',' to separate ranges. No spaces or ';'
2193 // --------------------------------------------------------------------------------
2194 function PclTarHandleExtractByIndexList(
2202 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleExtractByIndexList",
2203 "archive='$p_tarname', index_string='$p_index_string', list, path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2207 // ----- TBC : I should check the string by a regexp
2209 // ----- Check the path
2210 if (($p_path == "") ||
((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path, 0,
2213 $p_path = "./" . $p_path;
2216 // ----- Look for path to remove format (should end by /)
2217 if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
2218 $p_remove_path .= '/';
2220 $p_remove_path_size = strlen($p_remove_path);
2222 // ----- Open the tar file
2223 if ($p_tar_mode == "tar") {
2224 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in binary read mode");
2225 $v_tar = @fopen
($p_tarname, "rb");
2227 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in gzip binary read mode");
2228 $v_tar = @gzopen
($p_tarname, "rb");
2231 // ----- Check that the archive is open
2234 PclErrorLog(-2, "Unable to open archive '$p_tarname' in binary read mode");
2237 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2239 return PclErrorCode();
2242 // ----- Manipulate the index list
2243 $v_list = explode(",", $p_index_string);
2246 // ----- Loop on the index list
2248 for ($i = 0; ($i < sizeof($v_list)) && ($v_result); $i++
) {
2249 TrFctMessage(__FILE__
, __LINE__
, 3, "Looking for index part '$v_list[$i]'");
2251 // ----- Extract range
2252 $v_index_list = explode("-", $v_list[$i]);
2253 $v_size_index_list = sizeof($v_index_list);
2254 if ($v_size_index_list == 1) {
2255 TrFctMessage(__FILE__
, __LINE__
, 3, "Only one index '$v_index_list[0]'");
2257 // ----- Do the extraction
2258 $v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[0], $p_list_detail,
2259 $p_path, $p_remove_path, $p_tar_mode);
2261 if ($v_size_index_list == 2) {
2262 TrFctMessage(__FILE__
, __LINE__
, 3, "Two indexes '$v_index_list[0]' and '$v_index_list[1]'");
2264 // ----- Do the extraction
2265 $v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[1], $p_list_detail,
2266 $p_path, $p_remove_path, $p_tar_mode);
2271 // ----- Close the tarfile
2272 if ($p_tar_mode == "tar") {
2279 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2284 // --------------------------------------------------------------------------------
2286 // --------------------------------------------------------------------------------
2287 // Function : PclTarHandleExtractByIndex()
2291 // --------------------------------------------------------------------------------
2292 function PclTarHandleExtractByIndex(
2302 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleExtractByIndex",
2303 "archive_descr='$p_tar', index_current=$p_index_current, index_start='$p_index_start', index_stop='$p_index_stop', list, path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2307 // TBC : I should replace all $v_tar by $p_tar in this function ....
2310 // ----- Look the number of elements already in $p_list_detail
2311 $v_nb = sizeof($p_list_detail);
2313 // ----- Read the blocks
2314 while (!($v_end_of_file = ($p_tar_mode == "tar" ?
feof($v_tar) : gzeof($v_tar)))) {
2315 TrFctMessage(__FILE__
, __LINE__
, 3, "Looking for next file ...");
2316 TrFctMessage(__FILE__
, __LINE__
, 3, "Index current=$p_index_current, range=[$p_index_start, $p_index_stop])");
2318 if ($p_index_current > $p_index_stop) {
2319 TrFctMessage(__FILE__
, __LINE__
, 2, "Stop extraction, past stop index");
2323 // ----- Clear cache of file infos
2326 // ----- Reset extract tag
2327 $v_extract_file = false;
2328 $v_extraction_stopped = 0;
2330 // ----- Read the 512 bytes header
2331 if ($p_tar_mode == "tar") {
2332 $v_binary_data = fread($v_tar, 512);
2334 $v_binary_data = gzread($v_tar, 512);
2337 // ----- Read the header properties
2338 if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2340 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2345 // ----- Look for empty blocks to skip
2346 if ($v_header['filename'] == "") {
2347 TrFctMessage(__FILE__
, __LINE__
, 2, "Empty block found. End of archive ?");
2351 TrFctMessage(__FILE__
, __LINE__
, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
2353 // ----- Look if file is in the range to be extracted
2354 if (($p_index_current >= $p_index_start) && ($p_index_current <= $p_index_stop)) {
2355 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$v_header[filename]' is in the range to be extracted");
2356 $v_extract_file = true;
2358 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$v_header[filename]' is out of the range");
2359 $v_extract_file = false;
2362 // ----- Look if this file need to be extracted
2363 if ($v_extract_file) {
2364 if (($v_result = PclTarHandleExtractFile($v_tar, $v_header, $p_path, $p_remove_path, $p_tar_mode)) != 1) {
2366 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2370 } // ----- Look for file that is not to be extracted
2373 TrFctMessage(__FILE__
, __LINE__
, 2, "Jump file '$v_header[filename]'");
2374 TrFctMessage(__FILE__
, __LINE__
, 4,
2375 "Position avant jump [" . ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) . "]");
2377 // ----- Jump to next file
2378 if ($p_tar_mode == "tar") {
2379 fseek($v_tar, ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) +
(ceil(($v_header['size'] / 512)) * 512));
2381 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2384 TrFctMessage(__FILE__
, __LINE__
, 4,
2385 "Position apr�s jump [" . ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) . "]");
2388 if ($p_tar_mode == "tar") {
2389 $v_end_of_file = feof($v_tar);
2391 $v_end_of_file = gzeof($v_tar);
2394 // ----- File name and properties are logged if listing mode or file is extracted
2395 if ($v_extract_file) {
2396 TrFctMessage(__FILE__
, __LINE__
, 2, "Memorize info about file '$v_header[filename]'");
2398 // ----- Log extracted files
2399 if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) {
2402 if ((substr($v_header['filename'], 0, 1) == "/") && ($v_file_dir == "")) {
2406 // ----- Add the array describing the file into the list
2407 $p_list_detail[$v_nb] = $v_header;
2413 // ----- Increment the current file index
2418 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2423 // --------------------------------------------------------------------------------
2425 // --------------------------------------------------------------------------------
2426 // Function : PclTarHandleExtractFile()
2430 // --------------------------------------------------------------------------------
2431 function PclTarHandleExtractFile($p_tar, &$v_header, $p_path, $p_remove_path, $p_tar_mode) {
2432 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleExtractFile",
2433 "archive_descr='$p_tar', path=$p_path, remove_path='$p_remove_path', tar_mode=$p_tar_mode");
2436 // TBC : I should replace all $v_tar by $p_tar in this function ....
2438 $v_extract_file = 1;
2440 $p_remove_path_size = strlen($p_remove_path);
2442 // ----- Look for path to remove
2443 if (($p_remove_path != "")
2444 && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)
2446 TrFctMessage(__FILE__
, __LINE__
, 3, "Found path '$p_remove_path' to remove in file '$v_header[filename]'");
2447 // ----- Remove the path
2448 $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
2449 TrFctMessage(__FILE__
, __LINE__
, 3, "Resulting file is '$v_header[filename]'");
2452 // ----- Add the path to the file
2453 if (($p_path != "./") && ($p_path != "/")) {
2454 // ----- Look for the path end '/'
2455 while (substr($p_path, -1) == "/") {
2456 TrFctMessage(__FILE__
, __LINE__
, 3, "Destination path [$p_path] ends by '/'");
2457 $p_path = substr($p_path, 0, strlen($p_path) - 1);
2458 TrFctMessage(__FILE__
, __LINE__
, 3, "Modified to [$p_path]");
2461 // ----- Add the path
2462 if (substr($v_header['filename'], 0, 1) == "/") {
2463 $v_header['filename'] = $p_path . $v_header['filename'];
2465 $v_header['filename'] = $p_path . "/" . $v_header['filename'];
2470 TrFctMessage(__FILE__
, __LINE__
, 2, "Extracting file (with path) '$v_header[filename]', size '$v_header[size]'");
2472 // ----- Check that the file does not exists
2473 if (file_exists($v_header['filename'])) {
2474 TrFctMessage(__FILE__
, __LINE__
, 2, "File '$v_header[filename]' already exists");
2476 // ----- Look if file is a directory
2477 if (is_dir($v_header['filename'])) {
2478 TrFctMessage(__FILE__
, __LINE__
, 2, "Existing file '$v_header[filename]' is a directory");
2480 // ----- Change the file status
2481 $v_header['status'] = "already_a_directory";
2483 // ----- Skip the extract
2484 $v_extraction_stopped = 1;
2485 $v_extract_file = 0;
2486 } // ----- Look if file is write protected
2488 if (!is_writeable($v_header['filename'])) {
2489 TrFctMessage(__FILE__
, __LINE__
, 2, "Existing file '$v_header[filename]' is write protected");
2491 // ----- Change the file status
2492 $v_header['status'] = "write_protected";
2494 // ----- Skip the extract
2495 $v_extraction_stopped = 1;
2496 $v_extract_file = 0;
2497 } // ----- Look if the extracted file is older
2499 if (filemtime($v_header['filename']) > $v_header['mtime']) {
2500 TrFctMessage(__FILE__
, __LINE__
, 2,
2501 "Existing file '$v_header[filename]' is newer (" . date("l dS of F Y h:i:s A",
2502 filemtime($v_header['filename'])) . ") than the extracted file (" . date("l dS of F Y h:i:s A",
2503 $v_header['mtime']) . ")");
2505 // ----- Change the file status
2506 $v_header['status'] = "newer_exist";
2508 // ----- Skip the extract
2509 $v_extraction_stopped = 1;
2510 $v_extract_file = 0;
2514 } // ----- Check the directory availability and create it if necessary
2516 if ($v_header['typeflag'] == "5") {
2517 $v_dir_to_check = $v_header['filename'];
2519 if (!strstr($v_header['filename'], "/")) {
2520 $v_dir_to_check = "";
2522 $v_dir_to_check = dirname($v_header['filename']);
2526 if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1) {
2527 TrFctMessage(__FILE__
, __LINE__
, 2, "Unable to create path for '$v_header[filename]'");
2529 // ----- Change the file status
2530 $v_header['status'] = "path_creation_fail";
2532 // ----- Skip the extract
2533 $v_extraction_stopped = 1;
2534 $v_extract_file = 0;
2538 // ----- Do the real bytes extraction (if not a directory)
2539 if (($v_extract_file) && ($v_header['typeflag'] != "5")) {
2540 // ----- Open the destination file in write mode
2541 if (($v_dest_file = @fopen
($v_header['filename'], "wb")) == 0) {
2542 TrFctMessage(__FILE__
, __LINE__
, 2, "Error while opening '$v_header[filename]' in write binary mode");
2544 // ----- Change the file status
2545 $v_header['status'] = "write_error";
2547 // ----- Jump to next file
2548 TrFctMessage(__FILE__
, __LINE__
, 2, "Jump to next file");
2549 if ($p_tar_mode == "tar") {
2550 fseek($v_tar, ftell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2552 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2555 TrFctMessage(__FILE__
, __LINE__
, 2, "Start extraction of '$v_header[filename]'");
2558 $n = floor($v_header['size'] / 512);
2559 for ($i = 0; $i < $n; $i++
) {
2560 TrFctMessage(__FILE__
, __LINE__
, 3, "Read complete 512 bytes block number " . ($i +
1));
2561 if ($p_tar_mode == "tar") {
2562 $v_content = fread($v_tar, 512);
2564 $v_content = gzread($v_tar, 512);
2566 fwrite($v_dest_file, $v_content, 512);
2568 if (($v_header['size'] %
512) != 0) {
2569 TrFctMessage(__FILE__
, __LINE__
, 3, "Read last " . ($v_header['size'] %
512) . " bytes in a 512 block");
2570 if ($p_tar_mode == "tar") {
2571 $v_content = fread($v_tar, 512);
2573 $v_content = gzread($v_tar, 512);
2575 fwrite($v_dest_file, $v_content, ($v_header['size'] %
512));
2578 // ----- Close the destination file
2579 fclose($v_dest_file);
2581 // ----- Change the file mode, mtime
2582 touch($v_header['filename'], $v_header['mtime']);
2583 //chmod($v_header['filename'], DecOct($v_header['mode']));
2586 // ----- Check the file size
2588 if (filesize($v_header['filename']) != $v_header['size']) {
2591 "Extracted file '$v_header[filename]' does not have the correct file size '" . filesize($v_filename) . "' ('$v_header[size]' expected). Archive may be corrupted.");
2594 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2596 return PclErrorCode();
2600 TrFctMessage(__FILE__
, __LINE__
, 2, "Extraction done");
2602 TrFctMessage(__FILE__
, __LINE__
, 2, "Extraction of file '$v_header[filename]' skipped.");
2604 // ----- Jump to next file
2605 TrFctMessage(__FILE__
, __LINE__
, 2, "Jump to next file");
2606 if ($p_tar_mode == "tar") {
2607 fseek($v_tar, ftell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2609 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2614 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2619 // --------------------------------------------------------------------------------
2621 // --------------------------------------------------------------------------------
2622 // Function : PclTarHandleDelete()
2626 // --------------------------------------------------------------------------------
2627 function PclTarHandleDelete($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode) {
2628 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleDelete", "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2632 // ----- Look for regular tar file
2633 if ($p_tar_mode == "tar") {
2635 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in binary read mode");
2636 if (($v_tar = @fopen
($p_tarname, "rb")) == 0) {
2638 PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2641 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2643 return PclErrorCode();
2646 // ----- Open a temporary file in write mode
2647 $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2648 TrFctMessage(__FILE__
, __LINE__
, 2, "Creating temporary archive file $v_temp_tarname");
2649 if (($v_temp_tar = @fopen
($v_temp_tarname, "wb")) == 0) {
2650 // ----- Close tar file
2654 PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2657 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2659 return PclErrorCode();
2661 } // ----- Look for compressed tar file
2663 // ----- Open the file in read mode
2664 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in gzip binary read mode");
2665 if (($v_tar = @gzopen
($p_tarname, "rb")) == 0) {
2667 PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2670 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2672 return PclErrorCode();
2675 // ----- Open a temporary file in write mode
2676 $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2677 TrFctMessage(__FILE__
, __LINE__
, 2, "Creating temporary archive file $v_temp_tarname");
2678 if (($v_temp_tar = @gzopen
($v_temp_tarname, "wb")) == 0) {
2679 // ----- Close tar file
2683 PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2686 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2688 return PclErrorCode();
2692 // ----- Read the blocks
2693 while (!($v_end_of_file = ($p_tar_mode == "tar" ?
feof($v_tar) : gzeof($v_tar)))) {
2694 TrFctMessage(__FILE__
, __LINE__
, 3, "Looking for next header ...");
2696 // ----- Clear cache of file infos
2699 // ----- Reset delete tag
2700 $v_delete_file = false;
2702 // ----- Read the first 512 block header
2703 if ($p_tar_mode == "tar") {
2704 $v_binary_data = fread($v_tar, 512);
2706 $v_binary_data = gzread($v_tar, 512);
2709 // ----- Read the header properties
2710 if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2711 // ----- Close the archive file
2712 if ($p_tar_mode == "tar") {
2714 fclose($v_temp_tar);
2717 gzclose($v_temp_tar);
2719 @unlink
($v_temp_tarname);
2722 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2727 // ----- Look for empty blocks to skip
2728 if ($v_header['filename'] == "") {
2729 TrFctMessage(__FILE__
, __LINE__
, 2, "Empty block found. End of archive ?");
2733 TrFctMessage(__FILE__
, __LINE__
, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
2735 // ----- Look for filenames to delete
2736 for ($i = 0, $v_delete_file = false; ($i < sizeof($p_file_list)) && (!$v_delete_file); $i++
) {
2737 // ----- Compare the file names
2738 // if ($p_file_list[$i] == $v_header['filename'])
2739 if (($v_len = strcmp($p_file_list[$i], $v_header['filename'])) <= 0) {
2741 TrFctMessage(__FILE__
, __LINE__
, 3, "Found that '$v_header[filename]' need to be deleted");
2742 $v_delete_file = true;
2744 TrFctMessage(__FILE__
, __LINE__
, 3, "Look if '$v_header[filename]' is a file in $p_file_list[$i]");
2745 if (substr($v_header['filename'], strlen($p_file_list[$i]), 1) == "/") {
2746 TrFctMessage(__FILE__
, __LINE__
, 3, "'$v_header[filename]' is a file in $p_file_list[$i]");
2747 $v_delete_file = true;
2753 // ----- Copy files that do not need to be deleted
2754 if (!$v_delete_file) {
2755 TrFctMessage(__FILE__
, __LINE__
, 2, "Keep file '$v_header[filename]'");
2757 // ----- Write the file header
2758 if ($p_tar_mode == "tar") {
2759 fputs($v_temp_tar, $v_binary_data, 512);
2761 gzputs($v_temp_tar, $v_binary_data, 512);
2764 // ----- Write the file data
2765 $n = ceil($v_header['size'] / 512);
2766 for ($i = 0; $i < $n; $i++
) {
2767 TrFctMessage(__FILE__
, __LINE__
, 3, "Read complete 512 bytes block number " . ($i +
1));
2768 if ($p_tar_mode == "tar") {
2769 $v_content = fread($v_tar, 512);
2770 fwrite($v_temp_tar, $v_content, 512);
2772 $v_content = gzread($v_tar, 512);
2773 gzwrite($v_temp_tar, $v_content, 512);
2777 // ----- File name and properties are logged if listing mode or file is extracted
2778 TrFctMessage(__FILE__
, __LINE__
, 2, "Memorize info about file '$v_header[filename]'");
2780 // ----- Add the array describing the file into the list
2781 $p_list_detail[$v_nb] = $v_header;
2782 $p_list_detail[$v_nb]['status'] = "ok";
2786 } // ----- Look for file that is to be deleted
2789 TrFctMessage(__FILE__
, __LINE__
, 2, "Start deletion of '$v_header[filename]'");
2790 TrFctMessage(__FILE__
, __LINE__
, 4,
2791 "Position avant jump [" . ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) . "]");
2793 // ----- Jump to next file
2794 if ($p_tar_mode == "tar") {
2795 fseek($v_tar, ftell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2797 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_header['size'] / 512)) * 512));
2800 TrFctMessage(__FILE__
, __LINE__
, 4,
2801 "Position apr�s jump [" . ($p_tar_mode == "tar" ?
ftell($v_tar) : gztell($v_tar)) . "]");
2804 // ----- Look for end of file
2805 if ($p_tar_mode == "tar") {
2806 $v_end_of_file = feof($v_tar);
2808 $v_end_of_file = gzeof($v_tar);
2812 // ----- Write the last empty buffer
2813 PclTarHandleFooter($v_temp_tar, $p_tar_mode);
2815 // ----- Close the tarfile
2816 if ($p_tar_mode == "tar") {
2818 fclose($v_temp_tar);
2821 gzclose($v_temp_tar);
2824 // ----- Unlink tar file
2825 if (!@unlink
($p_tarname)) {
2827 PclErrorLog(-11, "Error while deleting archive name $p_tarname");
2831 // ----- Rename tar file
2832 if (!@rename
($v_temp_tarname, $p_tarname)) {
2834 PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
2837 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2839 return PclErrorCode();
2843 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2848 // --------------------------------------------------------------------------------
2850 // --------------------------------------------------------------------------------
2851 // Function : PclTarHandleUpdate()
2855 // --------------------------------------------------------------------------------
2856 function PclTarHandleUpdate($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode, $p_add_dir, $p_remove_dir) {
2857 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleUpdate", "archive='$p_tarname', list, tar_mode=$p_tar_mode");
2860 $v_found_list = array();
2862 // ----- Look for regular tar file
2863 if ($p_tar_mode == "tar") {
2865 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in binary read mode");
2866 if (($v_tar = @fopen
($p_tarname, "rb")) == 0) {
2868 PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2871 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2873 return PclErrorCode();
2876 // ----- Open a temporary file in write mode
2877 $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2878 TrFctMessage(__FILE__
, __LINE__
, 2, "Creating temporary archive file $v_temp_tarname");
2879 if (($v_temp_tar = @fopen
($v_temp_tarname, "wb")) == 0) {
2880 // ----- Close tar file
2884 PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2887 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2889 return PclErrorCode();
2891 } // ----- Look for compressed tar file
2893 // ----- Open the file in read mode
2894 TrFctMessage(__FILE__
, __LINE__
, 3, "Open file in gzip binary read mode");
2895 if (($v_tar = @gzopen
($p_tarname, "rb")) == 0) {
2897 PclErrorLog(-2, "Unable to open file '$p_tarname' in binary read mode");
2900 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2902 return PclErrorCode();
2905 // ----- Open a temporary file in write mode
2906 $v_temp_tarname = uniqid("pcltar-") . ".tmp";
2907 TrFctMessage(__FILE__
, __LINE__
, 2, "Creating temporary archive file $v_temp_tarname");
2908 if (($v_temp_tar = @gzopen
($v_temp_tarname, "wb")) == 0) {
2909 // ----- Close tar file
2913 PclErrorLog(-1, "Unable to open file '$v_temp_tarname' in binary write mode");
2916 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
2918 return PclErrorCode();
2922 // ----- Prepare the list of files
2923 for ($i = 0; $i < sizeof($p_file_list); $i++
) {
2924 // ----- Reset the found list
2925 $v_found_list[$i] = 0;
2927 // ----- Calculate the stored filename
2928 $v_stored_list[$i] = $p_file_list[$i];
2929 if ($p_remove_dir != "") {
2930 if (substr($p_file_list[$i], -1) != '/') {
2931 $p_remove_dir .= "/";
2934 if (substr($p_file_list[$i], 0, strlen($p_remove_dir)) == $p_remove_dir) {
2935 $v_stored_list[$i] = substr($p_file_list[$i], strlen($p_remove_dir));
2936 TrFctMessage(__FILE__
, __LINE__
, 3,
2937 "Remove path '$p_remove_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
2940 if ($p_add_dir != "") {
2941 if (substr($p_add_dir, -1) == "/") {
2942 $v_stored_list[$i] = $p_add_dir . $v_stored_list[$i];
2944 $v_stored_list[$i] = $p_add_dir . "/" . $v_stored_list[$i];
2946 TrFctMessage(__FILE__
, __LINE__
, 3, "Add path '$p_add_dir' in file '$p_file_list[$i]' = '$v_stored_list[$i]'");
2948 $v_stored_list[$i] = PclTarHandlePathReduction($v_stored_list[$i]);
2949 TrFctMessage(__FILE__
, __LINE__
, 3, "After reduction '$v_stored_list[$i]'");
2953 // ----- Update file cache
2956 // ----- Read the blocks
2957 while (!($v_end_of_file = ($p_tar_mode == "tar" ?
feof($v_tar) : gzeof($v_tar)))) {
2958 TrFctMessage(__FILE__
, __LINE__
, 3, "Looking for next header ...");
2960 // ----- Clear cache of file infos
2963 // ----- Reset current found filename
2964 $v_current_filename = "";
2966 // ----- Reset delete tag
2967 $v_delete_file = false;
2969 // ----- Read the first 512 block header
2970 if ($p_tar_mode == "tar") {
2971 $v_binary_data = fread($v_tar, 512);
2973 $v_binary_data = gzread($v_tar, 512);
2976 // ----- Read the header properties
2977 if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1) {
2978 // ----- Close the archive file
2979 if ($p_tar_mode == "tar") {
2981 fclose($v_temp_tar);
2984 gzclose($v_temp_tar);
2986 @unlink
($v_temp_tarname);
2989 TrFctEnd(__FILE__
, __LINE__
, $v_result);
2994 // ----- Look for empty blocks to skip
2995 if ($v_header['filename'] == "") {
2996 TrFctMessage(__FILE__
, __LINE__
, 2, "Empty block found. End of archive ?");
3000 TrFctMessage(__FILE__
, __LINE__
, 2, "Found file '$v_header[filename]', size '$v_header[size]'");
3002 // ----- Look for filenames to update
3003 for ($i = 0, $v_update_file = false, $v_found_file = false; ($i < sizeof($v_stored_list)) && (!$v_update_file); $i++
) {
3004 TrFctMessage(__FILE__
, __LINE__
, 4, "Compare with file '$v_stored_list[$i]'");
3006 // ----- Compare the file names
3007 if ($v_stored_list[$i] == $v_header['filename']) {
3008 TrFctMessage(__FILE__
, __LINE__
, 3, "File '$v_stored_list[$i]' is present in archive");
3009 TrFctMessage(__FILE__
, __LINE__
, 3,
3010 "File '$v_stored_list[$i]' mtime=" . filemtime($p_file_list[$i]) . " " . date("l dS of F Y h:i:s A",
3011 filemtime($p_file_list[$i])));
3012 TrFctMessage(__FILE__
, __LINE__
, 3,
3013 "Archived mtime=" . $v_header['mtime'] . " " . date("l dS of F Y h:i:s A", $v_header['mtime']));
3015 // ----- Store found informations
3016 $v_found_file = true;
3017 $v_current_filename = $p_file_list[$i];
3019 // ----- Look if the file need to be updated
3020 if (filemtime($p_file_list[$i]) > $v_header['mtime']) {
3021 TrFctMessage(__FILE__
, __LINE__
, 3, "File '$p_file_list[$i]' need to be updated");
3022 $v_update_file = true;
3024 TrFctMessage(__FILE__
, __LINE__
, 3, "File '$p_file_list[$i]' does not need to be updated");
3025 $v_update_file = false;
3028 // ----- Flag the name in order not to add the file at the end
3029 $v_found_list[$i] = 1;
3031 TrFctMessage(__FILE__
, __LINE__
, 4, "File '$p_file_list[$i]' is not '$v_header[filename]'");
3035 // ----- Copy files that do not need to be updated
3036 if (!$v_update_file) {
3037 TrFctMessage(__FILE__
, __LINE__
, 2, "Keep file '$v_header[filename]'");
3039 // ----- Write the file header
3040 if ($p_tar_mode == "tar") {
3041 fputs($v_temp_tar, $v_binary_data, 512);
3043 gzputs($v_temp_tar, $v_binary_data, 512);
3046 // ----- Write the file data
3047 $n = ceil($v_header['size'] / 512);
3048 for ($j = 0; $j < $n; $j++
) {
3049 TrFctMessage(__FILE__
, __LINE__
, 3, "Read complete 512 bytes block number " . ($j +
1));
3050 if ($p_tar_mode == "tar") {
3051 $v_content = fread($v_tar, 512);
3052 fwrite($v_temp_tar, $v_content, 512);
3054 $v_content = gzread($v_tar, 512);
3055 gzwrite($v_temp_tar, $v_content, 512);
3059 // ----- File name and properties are logged if listing mode or file is extracted
3060 TrFctMessage(__FILE__
, __LINE__
, 2, "Memorize info about file '$v_header[filename]'");
3062 // ----- Add the array describing the file into the list
3063 $p_list_detail[$v_nb] = $v_header;
3064 $p_list_detail[$v_nb]['status'] = ($v_found_file ?
"not_updated" : "ok");
3068 } // ----- Look for file that need to be updated
3071 TrFctMessage(__FILE__
, __LINE__
, 2, "Start update of file '$v_current_filename'");
3073 // ----- Store the old file size
3074 $v_old_size = $v_header['size'];
3076 // ----- Add the file
3077 if (($v_result = PclTarHandleAddFile($v_temp_tar, $v_current_filename, $p_tar_mode, $v_header, $p_add_dir,
3078 $p_remove_dir)) != 1
3080 // ----- Close the tarfile
3081 if ($p_tar_mode == "tar") {
3083 fclose($v_temp_tar);
3086 gzclose($v_temp_tar);
3088 @unlink
($p_temp_tarname);
3090 // ----- Return status
3091 TrFctEnd(__FILE__
, __LINE__
, $v_result);
3097 TrFctMessage(__FILE__
, __LINE__
, 2, "Skip old file '$v_header[filename]'");
3099 // ----- Jump to next file
3100 if ($p_tar_mode == "tar") {
3101 fseek($v_tar, ftell($v_tar) +
(ceil(($v_old_size / 512)) * 512));
3103 gzseek($v_tar, gztell($v_tar) +
(ceil(($v_old_size / 512)) * 512));
3106 // ----- Add the array describing the file into the list
3107 $p_list_detail[$v_nb] = $v_header;
3108 $p_list_detail[$v_nb]['status'] = "updated";
3114 // ----- Look for end of file
3115 if ($p_tar_mode == "tar") {
3116 $v_end_of_file = feof($v_tar);
3118 $v_end_of_file = gzeof($v_tar);
3122 // ----- Look for files that does not exists in the archive and need to be added
3123 for ($i = 0; $i < sizeof($p_file_list); $i++
) {
3124 // ----- Look if file not found in the archive
3125 if (!$v_found_list[$i]) {
3126 TrFctMessage(__FILE__
, __LINE__
, 3, "File '$p_file_list[$i]' need to be added");
3128 // ----- Add the file
3129 if (($v_result = PclTarHandleAddFile($v_temp_tar, $p_file_list[$i], $p_tar_mode, $v_header, $p_add_dir,
3130 $p_remove_dir)) != 1
3132 // ----- Close the tarfile
3133 if ($p_tar_mode == "tar") {
3135 fclose($v_temp_tar);
3138 gzclose($v_temp_tar);
3140 @unlink
($p_temp_tarname);
3142 // ----- Return status
3143 TrFctEnd(__FILE__
, __LINE__
, $v_result);
3148 // ----- Add the array describing the file into the list
3149 $p_list_detail[$v_nb] = $v_header;
3150 $p_list_detail[$v_nb]['status'] = "added";
3155 TrFctMessage(__FILE__
, __LINE__
, 3, "File '$p_file_list[$i]' was already updated if needed");
3159 // ----- Write the last empty buffer
3160 PclTarHandleFooter($v_temp_tar, $p_tar_mode);
3162 // ----- Close the tarfile
3163 if ($p_tar_mode == "tar") {
3165 fclose($v_temp_tar);
3168 gzclose($v_temp_tar);
3171 // ----- Unlink tar file
3172 if (!@unlink
($p_tarname)) {
3174 PclErrorLog(-11, "Error while deleting archive name $p_tarname");
3178 // ----- Rename tar file
3179 if (!@rename
($v_temp_tarname, $p_tarname)) {
3181 PclErrorLog(-12, "Error while renaming temporary file $v_temp_tarname to archive name $p_tarname");
3184 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
3186 return PclErrorCode();
3190 TrFctEnd(__FILE__
, __LINE__
, $v_result);
3195 // --------------------------------------------------------------------------------
3197 // --------------------------------------------------------------------------------
3198 // Function : PclTarHandleReadHeader()
3202 // --------------------------------------------------------------------------------
3203 function PclTarHandleReadHeader($v_binary_data, &$v_header) {
3204 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleReadHeader", "");
3207 // ----- Read the 512 bytes header
3209 if ($p_tar_mode == "tar")
3210 $v_binary_data = fread($p_tar, 512);
3212 $v_binary_data = gzread($p_tar, 512);
3215 // ----- Look for no more block
3216 if (strlen($v_binary_data) == 0) {
3217 $v_header['filename'] = "";
3218 $v_header['status'] = "empty";
3221 TrFctEnd(__FILE__
, __LINE__
, $v_result, "End of archive found");
3226 // ----- Look for invalid block size
3227 if (strlen($v_binary_data) != 512) {
3228 $v_header['filename'] = "";
3229 $v_header['status'] = "invalid_header";
3230 TrFctMessage(__FILE__
, __LINE__
, 2, "Invalid block size : " . strlen($v_binary_data));
3233 PclErrorLog(-10, "Invalid block size : " . strlen($v_binary_data));
3236 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
3238 return PclErrorCode();
3241 // ----- Calculate the checksum
3243 // ..... First part of the header
3244 for ($i = 0; $i < 148; $i++
) {
3245 $v_checksum +
= ord(substr($v_binary_data, $i, 1));
3247 // ..... Ignore the checksum value and replace it by ' ' (space)
3248 for ($i = 148; $i < 156; $i++
) {
3249 $v_checksum +
= ord(' ');
3251 // ..... Last part of the header
3252 for ($i = 156; $i < 512; $i++
) {
3253 $v_checksum +
= ord(substr($v_binary_data, $i, 1));
3255 TrFctMessage(__FILE__
, __LINE__
, 3, "Calculated checksum : $v_checksum");
3257 // ----- Extract the values
3258 TrFctMessage(__FILE__
, __LINE__
, 2, "Header : '$v_binary_data'");
3259 $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor",
3262 // ----- Extract the checksum for check
3263 $v_header['checksum'] = OctDec(trim($v_data['checksum']));
3264 TrFctMessage(__FILE__
, __LINE__
, 3, "File checksum : $v_header[checksum]");
3265 if ($v_header['checksum'] != $v_checksum) {
3266 TrFctMessage(__FILE__
, __LINE__
, 2,
3267 "File checksum is invalid : $v_checksum calculated, $v_header[checksum] expected");
3269 $v_header['filename'] = "";
3270 $v_header['status'] = "invalid_header";
3272 // ----- Look for last block (empty block)
3273 if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
3274 $v_header['status'] = "empty";
3276 TrFctEnd(__FILE__
, __LINE__
, $v_result, "End of archive found");
3282 PclErrorLog(-13, "Invalid checksum : $v_checksum calculated, $v_header[checksum] expected");
3285 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
3287 return PclErrorCode();
3289 TrFctMessage(__FILE__
, __LINE__
, 2, "File checksum is valid ($v_checksum)");
3291 // ----- Extract the properties
3292 $v_header['filename'] = trim($v_data['filename']);
3293 TrFctMessage(__FILE__
, __LINE__
, 2, "Name : '$v_header[filename]'");
3294 $v_header['mode'] = OctDec(trim($v_data['mode']));
3295 TrFctMessage(__FILE__
, __LINE__
, 2, "Mode : '" . DecOct($v_header['mode']) . "'");
3296 $v_header['uid'] = OctDec(trim($v_data['uid']));
3297 TrFctMessage(__FILE__
, __LINE__
, 2, "Uid : '$v_header[uid]'");
3298 $v_header['gid'] = OctDec(trim($v_data['gid']));
3299 TrFctMessage(__FILE__
, __LINE__
, 2, "Gid : '$v_header[gid]'");
3300 $v_header['size'] = OctDec(trim($v_data['size']));
3301 TrFctMessage(__FILE__
, __LINE__
, 2, "Size : '$v_header[size]'");
3302 $v_header['mtime'] = OctDec(trim($v_data['mtime']));
3303 TrFctMessage(__FILE__
, __LINE__
, 2, "Date : " . date("l dS of F Y h:i:s A", $v_header['mtime']));
3304 if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
3305 $v_header['size'] = 0;
3306 TrFctMessage(__FILE__
, __LINE__
, 2, "Size (folder) : '$v_header[size]'");
3308 TrFctMessage(__FILE__
, __LINE__
, 2, "File typeflag : $v_header[typeflag]");
3309 /* ----- All these fields are removed form the header because they do not carry interesting info
3310 $v_header[link] = trim($v_data[link]);
3311 TrFctMessage(__FILE__, __LINE__, 2, "Linkname : $v_header[linkname]");
3312 $v_header[magic] = trim($v_data[magic]);
3313 TrFctMessage(__FILE__, __LINE__, 2, "Magic : $v_header[magic]");
3314 $v_header[version] = trim($v_data[version]);
3315 TrFctMessage(__FILE__, __LINE__, 2, "Version : $v_header[version]");
3316 $v_header[uname] = trim($v_data[uname]);
3317 TrFctMessage(__FILE__, __LINE__, 2, "Uname : $v_header[uname]");
3318 $v_header[gname] = trim($v_data[gname]);
3319 TrFctMessage(__FILE__, __LINE__, 2, "Gname : $v_header[gname]");
3320 $v_header[devmajor] = trim($v_data[devmajor]);
3321 TrFctMessage(__FILE__, __LINE__, 2, "Devmajor : $v_header[devmajor]");
3322 $v_header[devminor] = trim($v_data[devminor]);
3323 TrFctMessage(__FILE__, __LINE__, 2, "Devminor : $v_header[devminor]");
3326 // ----- Set the status field
3327 $v_header['status'] = "ok";
3330 TrFctEnd(__FILE__
, __LINE__
, $v_result);
3335 // --------------------------------------------------------------------------------
3337 // --------------------------------------------------------------------------------
3338 // Function : PclTarHandlerDirCheck()
3340 // Check if a directory exists, if not it creates it and all the parents directory
3341 // which may be useful.
3343 // $p_dir : Directory path to check (without / at the end).
3346 // -1 : Unable to create directory
3347 // --------------------------------------------------------------------------------
3348 function PclTarHandlerDirCheck($p_dir) {
3351 TrFctStart(__FILE__
, __LINE__
, "PclTarHandlerDirCheck", "$p_dir");
3353 // ----- Check the directory availability
3354 if ((is_dir($p_dir)) ||
($p_dir == "")) {
3355 TrFctEnd(__FILE__
, __LINE__
, "'$p_dir' is a directory");
3360 // ----- Look for file alone
3362 if (!strstr("$p_dir", "/"))
3364 TrFctEnd(__FILE__, __LINE__, "'$p_dir' is a file with no directory");
3369 // ----- Extract parent directory
3370 $p_parent_dir = dirname($p_dir);
3371 TrFctMessage(__FILE__
, __LINE__
, 3, "Parent directory is '$p_parent_dir'");
3373 // ----- Just a check
3374 if ($p_parent_dir != $p_dir) {
3375 // ----- Look for parent directory
3376 if ($p_parent_dir != "") {
3377 if (($v_result = PclTarHandlerDirCheck($p_parent_dir)) != 1) {
3378 TrFctEnd(__FILE__
, __LINE__
, $v_result);
3385 // ----- Create the directory
3386 TrFctMessage(__FILE__
, __LINE__
, 3, "Create directory '$p_dir'");
3387 if (!@mkdir
($p_dir, 0777)) {
3389 PclErrorLog(-8, "Unable to create directory '$p_dir'");
3392 TrFctEnd(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
3394 return PclErrorCode();
3398 TrFctEnd(__FILE__
, __LINE__
, $v_result, "Directory '$p_dir' created");
3403 // --------------------------------------------------------------------------------
3405 // --------------------------------------------------------------------------------
3406 // Function : PclTarHandleExtension()
3410 // --------------------------------------------------------------------------------
3411 function PclTarHandleExtension($p_tarname) {
3412 TrFctStart(__FILE__
, __LINE__
, "PclTarHandleExtension", "tar=$p_tarname");
3414 // ----- Look for file extension
3415 if ((substr($p_tarname, -7) == ".tar.gz") ||
(substr($p_tarname, -4) == ".tgz")) {
3416 TrFctMessage(__FILE__
, __LINE__
, 2, "Archive is a gzip tar");
3419 if (substr($p_tarname, -4) == ".tar") {
3420 TrFctMessage(__FILE__
, __LINE__
, 2, "Archive is a tar");
3424 PclErrorLog(-9, "Invalid archive extension");
3426 TrFctMessage(__FILE__
, __LINE__
, PclErrorCode(), PclErrorString());
3433 TrFctEnd(__FILE__
, __LINE__
, $p_mode);
3438 // --------------------------------------------------------------------------------
3441 // --------------------------------------------------------------------------------
3442 // Function : PclTarHandlePathReduction()
3446 // --------------------------------------------------------------------------------
3447 function PclTarHandlePathReduction($p_dir) {
3448 TrFctStart(__FILE__
, __LINE__
, "PclTarHandlePathReduction", "dir='$p_dir'");
3451 // ----- Look for not empty path
3453 // ----- Explode path by directory names
3454 $v_list = explode("/", $p_dir);
3456 // ----- Study directories from last to first
3457 for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
3458 // ----- Look for current path
3459 if ($v_list[$i] == ".") {
3460 // ----- Ignore this directory
3461 // Should be the first $i=0, but no check is done
3463 if ($v_list[$i] == "..") {
3464 // ----- Ignore it and ignore the $i-1
3467 if (($v_list[$i] == "") && ($i != (sizeof($v_list) - 1)) && ($i != 0)) {
3468 // ----- Ignore only the double '//' in path,
3469 // but not the first and last '/'
3471 $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ?
"/" . $v_result : "");
3479 TrFctEnd(__FILE__
, __LINE__
, $v_result);
3484 // --------------------------------------------------------------------------------
3487 // ----- End of double include look