PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Fill/fill.php

http://marcoratto.googlecode.com/
PHP | 336 lines | 236 code | 53 blank | 47 comment | 68 complexity | 396648665a6b9d8cdceb56e3d8eb2f19 MD5 | raw file
Possible License(s): GPL-2.0
  1. #!/usr/bin/env php
  2. <?PHP
  3. /*
  4. * Copyright (C) 2011 Marco Ratto
  5. *
  6. * This file is part of the project Fill.
  7. *
  8. * Fill is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * any later version.
  12. *
  13. * Fill is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with Fill; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. $SYNTAX = "Parameters: [OPTIONS] [SOURCE] [TARGET] [MAX_BYTES]\n";
  23. class Log4GPHP {
  24. // Only for this class
  25. public static $INTERNAL=6;
  26. // Severe errors that cause premature termination. Expect these to be immediately visible on a status console.
  27. public static $FATAL=5;
  28. // Other runtime errors or unexpected conditions. Expect these to be immediately visible on a status console.
  29. public static $ERROR = 4;
  30. // Use of deprecated APIs, poor use of API, 'almost' errors, other runtime situations that are undesirable or unexpected, but not necessarily "wrong". Expect these to be immediately visible on a status console.
  31. public static $WARN = 3;
  32. // Interesting runtime events (startup/shutdown). Expect these to be immediately visible on a console, so be conservative and keep to a minimum.
  33. public static $INFO = 2;
  34. // Detailed information on flow of through the system. Expect these to be written to logs only.
  35. public static $DEBUG = 1;
  36. // Detailed information on flow of through the system. Expect these to be written to logs only.
  37. public static $TRACE = 0;
  38. private static $LEVEL_NAMES = array(0=>"TRACE", 1=>"DEBUG", 2=>"INFO", 3=>"WARN", 4=>"ERROR", 5=>"FATAL", 6=>"INTERNAL");
  39. private static $loggingLevel = 0;
  40. private static function log($level, $message) {
  41. if ($level < self::$TRACE || $level > self::$INTERNAL) {
  42. echo("Logging level must be between TRACE(" . self::$DEBUG . ") and FATAL(" . self::$FATAL . ")");
  43. }
  44. if (($level < self::$loggingLevel) && ($level != self::$INTERNAL)) {
  45. return;
  46. }
  47. echo self::$LEVEL_NAMES[$level] . ": " . $message . "\n";
  48. }
  49. public static function print_r($level, $var) {
  50. if ($level < self::$TRACE || $level > self::$INTERNAL) {
  51. echo("Logging level must be between TRACE(" . self::$DEBUG . ") and FATAL(" . self::$FATAL . ")");
  52. }
  53. if (($level < self::$loggingLevel) && ($level != self::$INTERNAL)) {
  54. return;
  55. }
  56. $results = print_r($var, true);
  57. echo self::$LEVEL_NAMES[$level] . "-" . $results . "\n";
  58. }
  59. public function setLoggingLevel($level) {
  60. if ($level < self::$TRACE || $level>self::$FATAL) {
  61. return;
  62. }
  63. self::$loggingLevel = $level;
  64. self::log(self::$INTERNAL, "Level set to " . self::$LEVEL_NAMES[self::$loggingLevel]);
  65. }
  66. public static function getLoggingLevel() {
  67. return self::$loggingLevel;
  68. }
  69. public static function trace ($message) {
  70. self::log(self::$TRACE, $message);
  71. }
  72. public static function debug ($message) {
  73. self::log(self::$DEBUG, $message);
  74. }
  75. public static function info($message) {
  76. self::log(self::$INFO, $message);
  77. }
  78. public static function warn($message) {
  79. self::log(self::$WARN, $message);
  80. }
  81. public static function error($message) {
  82. self::log(self::$ERROR, $message);
  83. }
  84. public static function fatal($message) {
  85. self::log(self::$FATAL, $message);
  86. }
  87. }
  88. function parseArgs($argv) {
  89. array_shift($argv);
  90. Log4GPHP::print_r(Log4GPHP::$TRACE, $argv);
  91. $out = array();
  92. for ($j=0; $j <count($argv) ; $j++) {
  93. // foreach ($argv as $arg) {
  94. $arg = $argv[$j];
  95. if (substr($arg,0,2) == '--'){
  96. $eqPos = strpos($arg,'=');
  97. if ($eqPos === false) {
  98. $key = substr($arg,2);
  99. $out[$key] = isset($out[$key]) ? $out[$key] : true;
  100. } else {
  101. $key = substr($arg,2,$eqPos-2);
  102. $out[$key] = substr($arg,$eqPos+1);
  103. }
  104. } else if (substr($arg,0,1) == '-'){
  105. $eqPos = strpos($arg,'=');
  106. if ($eqPos === false){
  107. $key = substr($arg,1);
  108. $out[$key] = isset($out[$key]) ? $out[$key] : true;
  109. } else {
  110. $key = substr($arg,1,$eqPos-1);
  111. $out[$key] = substr($arg,$eqPos+1);
  112. }
  113. } else {
  114. $out[] = $arg;
  115. }
  116. }
  117. return $out;
  118. }
  119. Log4GPHP::setLoggingLevel(Log4GPHP::$TRACE);
  120. Log4GPHP::info("argc=$argc");
  121. if ($argc < 3) {
  122. print $SYNTAX;
  123. exit(1);
  124. }
  125. $params = parseArgs($argv);
  126. Log4GPHP::print_r(Log4GPHP::$INFO, $params);
  127. $size = $params['size'];
  128. Log4GPHP::info("size=$size");
  129. $mv = 0;
  130. if (array_key_exists('mv', $params)) {
  131. $mv = 1;
  132. }
  133. Log4GPHP::info("mv=$mv");
  134. $counter_target_dir = 1;
  135. $flag_counter = 0;
  136. if (array_key_exists('counter', $params)) {
  137. $counter_target_dir = 1;
  138. $flag_counter = 1;
  139. }
  140. Log4GPHP::info("flag_counter=$flag_counter");
  141. $mkdir = 0;
  142. if (array_key_exists('mkdir', $params)) {
  143. $mkdir = 1;
  144. }
  145. Log4GPHP::info("mkdir=$mkdir");
  146. Log4GPHP::info("gb=" . array_key_exists('gb', $params));
  147. Log4GPHP::info("mb=" . array_key_exists('mb', $params));
  148. Log4GPHP::info("kb=" . array_key_exists('kb', $params));
  149. $multiplier = 1;
  150. if (array_key_exists('gb', $params)) {
  151. Log4GPHP::info("-gb setted");
  152. $multiplier = 1024 * 1024 * 1024;
  153. }
  154. if (array_key_exists('mb', $params)) {
  155. Log4GPHP::info("-mb setted");
  156. $multiplier = 1024 * 1024;
  157. }
  158. if (array_key_exists('kb', $params)) {
  159. Log4GPHP::info("-kb setted");
  160. $multiplier = 1024;
  161. }
  162. Log4GPHP::info("multiplier=" . $multiplier);
  163. $target_max_bytes= $size * $multiplier;
  164. Log4GPHP::info("target_max_bytes=$target_max_bytes");
  165. $source = $params['source'];
  166. $target_dir = $params['target'];
  167. if ($flag_counter == 1) {
  168. $target= $target_dir . $counter_target_dir;
  169. }
  170. if (($mkdir == 1) && (is_dir($target) == false)) {
  171. Log4GPHP::info("Try to create directory $target.");
  172. mkdir($target);
  173. }
  174. if (is_dir($target) == false) {
  175. echo "ERROR: $target not exist!\n";
  176. exit(1);
  177. }
  178. $listOfFiles = array();
  179. scan_directory_recursively($source, 'my_handler');
  180. Log4GPHP::info("target_max_bytes=$target_max_bytes");
  181. arsort($listOfFiles);
  182. // Log4GPHP::print_r(Log4GPHP::$INFO, $listOfFiles);
  183. $counter_max_bytes = $target_max_bytes;
  184. while ($counter_max_bytes > 0) {
  185. Log4GPHP::info("Remaining $counter_max_bytes bytes");
  186. $key = "";
  187. $value = -1;
  188. Log4GPHP::info("Try to search a file on the total " . count($listOfFiles));
  189. foreach ($listOfFiles as $filename=>$filesize) {
  190. if ($filesize <= $counter_max_bytes) {
  191. Log4GPHP::info("Found file $filename ($filesize bytes).");
  192. $key = $filename;
  193. $value = $filesize;
  194. break;
  195. }
  196. }
  197. if ($value != -1) {
  198. $target= $target_dir . $counter_target_dir;
  199. if (($mkdir == 1) && (is_dir($target) == false)) {
  200. Log4GPHP::info("Try to create directory $target.");
  201. mkdir($target);
  202. }
  203. if (is_dir($target) == false) {
  204. Log4GPHP::error("Directory $target not exist!");
  205. exit(1);
  206. }
  207. $target_file = $target . "/" . basename($key);
  208. if (file_exists($target_file)) {
  209. Log4GPHP::warn("File $target_file ($value bytes) already exists! Skipped.");
  210. } else {
  211. Log4GPHP::info("Copy $key to $target_file ($value bytes)");
  212. if ($mv) {
  213. rename($key, $target_file);
  214. } else {
  215. copy($key, $target_file);
  216. }
  217. }
  218. $counter_max_bytes -= $value;
  219. unset($listOfFiles[$key]);
  220. } else {
  221. if (count($listOfFiles) == 0) {
  222. Log4GPHP::info("Finished to copy all files.");
  223. $counter_max_bytes = 0;
  224. } else {
  225. $counter_max_bytes = $target_max_bytes;
  226. $counter_target_dir++;
  227. Log4GPHP::info("Pass to a new directory with counter $counter_target_dir.");
  228. }
  229. }
  230. }
  231. exit(0);
  232. function my_handler($filename) {
  233. GLOBAL $target_max_bytes;
  234. GLOBAL $listOfFiles;
  235. $size = filesize($filename);
  236. $listOfFiles["$filename"] = $size;
  237. // echo "$filename=$size\n";
  238. }
  239. function scan_directory_recursively($directory, $callback) {
  240. // if the path has a slash at the end we remove it here
  241. if(substr($directory,-1) == '/') {
  242. $directory = substr($directory, 0, -1);
  243. }
  244. // if the path is not valid or is not a directory ...
  245. if(!file_exists($directory) || !is_dir($directory)) {
  246. // ... we return false and exit the function
  247. return FALSE;
  248. // ... else if the path is readable
  249. } elseif (is_readable($directory)) {
  250. // we open the directory
  251. $handle = opendir($directory);
  252. // and scan through the items inside
  253. while (FALSE !== ($file = readdir($handle))) {
  254. // if the filepointer is not the current directory
  255. // or the parent directory
  256. if($file != '.' && $file != '..') {
  257. // we build the new path to scan
  258. $path = $directory.'/'.$file;
  259. // if the path is readable
  260. if (is_readable($path)) {
  261. // we split the new path by directories
  262. $subdirectories = explode('/', $path);
  263. // if the new path is a directory
  264. if (is_dir($path)) {
  265. // print end($subdirectories);
  266. scan_directory_recursively($path, $callback);
  267. } else {
  268. call_user_func($callback, $path);
  269. }
  270. }
  271. }
  272. }
  273. // close the directory
  274. closedir($handle);
  275. // return file list
  276. return TRUE;
  277. // if the path is not readable ...
  278. }else{
  279. // ... we return false
  280. return FALSE;
  281. }
  282. }
  283. ?>