#!/usr/bin/php --device possible modes are: always - force overwrites in all cases diff - only overwrites if there's a difference in file size never - never overwrites ask - ask for overwriting each time Defaults to ask. */ function term($sig) { p_log("Caught signal {$sig}."); echo $GLOBALS['blank'] . "\r"; error($sig == 2 ? 'User interrupt. Aborting.' : "Terminating."); exit; } $a = pcntl_signal(SIGTERM, "term"); $b = pcntl_signal(SIGINT, "term"); $arga = args(1); // config define("colorize",true); define("home",dirfix(getenv("HOME"))); define("target",home . "Videos"); define("unmount",true); // unmount after successfull copying when mounted by this script ? define("cdrom",!empty($arga['device']) ? $arga['device'] : "/dev/sr1||/dev/sr0||/dev/cdrom"); // seperate multiple posibilities with || define("cdtype","udf"); // cd type to check for when traversing mountpoints define("ftype","MPG"); // file type to search for define("block",1048576); // blocksize to use when copying date_default_timezone_set("Europe/Stockholm"); // internal variables, do not change except the filename of the logfile. $target = dirfix(target); $log = fopen($target . "dvd.log","a"); $UID = posix_getuid(); $devices = explode("||",cdrom); $mountpoint = false; $blk_dev = false; $blank = NULL; for($aio = 0; $aio < 124; $aio++) $blank .= " "; $ovw = !empty($arga['overwrite']) ? $arga['overwrite'] : 'ask'; $stats = Array("files" => 0, "time" => 0, "size" => 0); if(!$log) error("Couldn't open log."); // cdrom checks & mounter $exists = false; foreach($devices as $device) { if(file_exists($device)) // luckily even returns true on sockets & block devices { $blk_dev = $device; } } if(!$blk_dev) error("Can't find any block cdrom device. Please check that " . str_replace("||"," or ",cdrom) . " exists or update the config"); succ("Selected a block device specified in config ({$blk_dev})."); $m = mnts(); foreach($m as $mount) { if($mount['type'] == cdtype) { if($mount['block_device'] == $blk_dev) { $mountpoint = $mount['mountpoint']; succ("Found cdrom device {$blk_dev} mounted at " . $mountpoint); } else { warn("A device which probaly is a cdrom has been found ({$mount['block_device']}), but not one of the block devices you specified in the config."); } } } if(!$mountpoint) // mount the CD drive { info("Couldn't find any mounted CD device. Mounting it myself."); if($UID != 0) error("Can't mount without being root."); p_log("UID = {$UID}, continuing..."); $mpoint = dirfix(sys_get_temp_dir()) . "cdrom" . rand(1,10); // I.E /tmp/cdrom5 if(!is_dir($mpoint)) mkdir($mpoint); $mcmd = "mount -t " . cdtype . " " . $blk_dev . " " . $mpoint; shell($mcmd); $f = is_mounted($mpoint); if($f) { succ("Successfully mounted " . $blk_dev . " at " . $mpoint); $mountpoint = $mpoint; } else { error("Something went wrong with mounting " . $blk_dev); } } // every shit is passed now and the cd must be mounted at $mountpoint $mountpoint = dirfix($mountpoint); $asterixd = $mountpoint . "*."; $fn1 = $asterixd . strtolower(ftype); $fn2 = $asterixd . strtoupper(ftype); $fn3 = $mountpoint . "*/*." . strtolower(ftype); $fn4 = $mountpoint . "*/*." . strtoupper(ftype); $files1 = glob($fn1); $files2 = glob($fn2); $files3 = glob($fn3); $files4 = glob($fn4); $movies = array_merge($files1,$files2,$files3,$files4); // $movies contains all files found with the specified filetype in the mountpoint and one level deep directories, file type was used case insensitive foreach($movies as $movie) { $n = basename($movie); $b = ext($n,true)[1]; $year = substr($b,0,2); $month = substr($b,2,2); $day = substr($b,4,2); $y = (int) $year; $ccfl = substr(date("Y"),0,2); // current century first letters if($y > date("y")) { $year = $ccfl-1 . $year; } else { $year = $ccfl . $year; } $yd = dirfix($target . $year); cdir($yd); $md = dirfix($yd . $month); cdir($md); $dd = dirfix($md . $day); cdir($dd); $o = $dd . $n; $s = filesize($movie); $size = formatsize($s); $cont = true; $ow = false; if(file_exists($o)) { $osize = filesize($o); if($ovw == 'always') { $ow = true; info("Overwriting {$o} because overwrite is set to always."); } elseif($ovw == "never") { $cont = false; info("Skipping file {$movie} because overwrite is set to never."); } elseif($ovw == "diff") { if($osize == $s) { $cont = false; info("Not overwriting {$o}."); } else { info("Overwriting {$o} because of difference in size."); } } else { if($ovw != "ask") warn("Unknown value for option overwrite, falling back to default: ask"); if($osize == $s) { $m = "File {$o} already exists and has the same size as {$movie} ({$size}), shall we override it anyways ? [y/n]: "; } else { $m = "File {$o} already exists, shall we override it ? ({$size}/" . formatsize($osize) . ") [y/n]: "; } echo colorize ? "\033[33m{$m}\033[0m": $m; p_log("Prompting if we shall override {$o} with {$movie}..."); $i = fopen("php://stdin","r"); $l = fgets($i); fclose($i); $l = substr($l,0,-1); $l = strtolower($l); p_log("User response: {$l}"); if($l != "y") { $cont = false; info("Not overwriting."); } else { $ow = true; } } } if($cont) { if($ow) { $msg = "Overriding {$o} with {$movie}"; } else { $msg = "Copying {$n} to {$o}..."; } echo colorize ? "\033[01;34m{$msg} ({$size})\033[0m\r": $msg . " ({$size})\r"; p_log($msg); $h = fopen($movie,"r") or error("Cannot open {$movie} for reading."); $oh = fopen($o,"w") or error("Cannot open {$o} for writing."); $pos = 0; $pchunk = $s / 100; $t1 = time(); while(!feof($h)) { echo $blank . "\r"; if($pos == 0) { $m = "{$msg} (0 Byte of {$size}, 0%)"; } else { $percentage = round($pos / $pchunk,2); $copied = formatsize($pos); $tss = time()-$t1; // time since start $speed = $tss == 0 ? "0 Bytes" : formatsize($pos/$tss); $m = "{$msg} ({$copied} of {$size}, {$speed}/s, {$percentage}%)"; } echo colorize ? "\033[01;34m{$m}\033[0m\r": $m . "\r"; fwrite($oh,fread($h,block)); $pos += block; } $t2 = time(); // time finished fclose($h); fclose($oh); echo $blank . "\r"; if(file_exists($o)) { $s1 = filesize($o); $s2 = filesize($movie); $tss = $t2-$t1; $stats['files']++; $stats['time'] += $tss; $stats['size'] += $s2; if($s1 != $s2) warn("Size missmatch between files {$o} and {$movie} ({$s1} != {$s2})! The target file may be corrupt."); succ("Successfully copied {$movie} to {$o}, {$size} in " . formattime($tss) . "."); } else { warn("Something went wrong that {$n} couldn't be copied :("); } } } succ("Copied {$stats['files']} files (" . formatsize($stats['size']) . ") in " . formattime($stats['time']) . " successfully! Exiting..."); // exit if($arga['eject'] == true) { info("Ejecting disk as you requested."); shell("eject {$blk_dev}"); } error(NULL,1); // functions function dirfix($dir) { $a = substr($dir,-1) == DIRECTORY_SEPARATOR ? $dir : $dir . DIRECTORY_SEPARATOR; return $a; } // log functions function info($msg, $newline = PHP_EOL) { p_log($msg); echo colorize ? "\033[36m{$msg}\033[0m" . $newline : $msg . $newline; } function succ($msg, $newline = PHP_EOL) { p_log($msg); echo colorize ? "\033[32m{$msg}\033[0m" . $newline : $msg . $newline; } function warn($msg, $newline = PHP_EOL) { $bt = debug_backtrace(); $caller = array_shift($bt); $line = $caller['line']; p_log("Warning (line {$line}): " . $msg); echo colorize ? "\033[1;33mWarning (line {$line}): {$msg}\033[0m" . $newline : $msg . $newline; } function is_mounted($dir) { foreach(mnts() as $point) { if($point['mountpoint'] == $dir) { return true; } } } function cdir($dir) // checks if a directory exists and creates it if it doesn't { if(!is_dir($dir)) { mkdir($dir); info("Created directory {$dir}"); } } function error($msg,$q = false) { $bt = debug_backtrace(); $caller = array_shift($bt); $line = $caller['line']; if(!$q) { p_log("function error() called from line {$line}. Exiting with message: {$msg}",$msg); } else { p_log("Exiting."); } if(!$q) echo(colorize ? "\033[31mERROR: {$msg}\033[0m" . PHP_EOL : $msg . PHP_EOL); @$p = $GLOBALS['mpoint']; if(!empty($p)) { info("Unmounting CD if mounted myself due to coming exit."); if(!is_mounted($p)) { warn("{$p} isn't mounted!"); } else { shell("umount {$p}"); } rmdir($p); } fclose($GLOBALS['log']); exit; } function p_log($txt) { fwrite($GLOBALS['log'],date("Y-m-d H:i:s") . " " . $txt . PHP_EOL); } function shell($cmd) { $cmd = $cmd . " 2>&1"; p_log("SHELL {$cmd}" . PHP_EOL); $sh = popen($cmd,"r"); while(!feof($sh)) { $buff = fread($sh,1024); echo $buff; fwrite($GLOBALS['log'],$buff); } pclose($sh); p_log("Shell exited."); } function mnts() // mount list { $out = Array(); $mounts = file("/proc/mounts"); foreach($mounts as $mount) { $mount = substr($mount,0,-1); $m = explode(" ",$mount); list($blk,$point,$type) = $m; $out[] = Array('block_device' => $blk, 'mountpoint' => $point, 'type' => $type); } return $out; } function formatsize($size) { if($size == 0) return "0 Bytes"; if($size == 1) return "1 Byte"; if($size >= 1024 * 1024 * 1024) { return round($size / 1024 / 1024 / 1024,2) . " GiB"; } elseif($size >= 1024 * 1024) { return round($size / 1024 / 1024,2) . " MiB"; } elseif($size >= 1024) { return round($size / 1024,2) . " KiB"; } elseif($size <= 1024) { return "{$size} Bytes"; } } function formattime($time) { if($time > 3600) { return round($time / 3600,2) . " Hours"; } elseif($time > 60) { return round($time / 60,2) . " Minutes"; } else { return $time . " Seconds"; } } function ext($file,$split = false) { $extension = explode(".",$file); $asize = sizeof($extension); $ext = strtolower($extension[$asize-1]); if(!$split) { return $ext; } else { unset($extension[$asize-1]); return array($ext,implode(".",$extension)); } } function args($lowercase = false) { function rmdash($str) { if($str[0] == "-" && $str[1] != "-") { return substr($str,1); } elseif($str[0] == "-" && $str[1] == "-") { return substr($str,2); } else { return $str; } } $argc = $GLOBALS['argc']; $argv = $GLOBALS['argv']; $arga = Array(); $i = 1; unset($argv[0]); if($argc > 1) { for(; $i < $argc; $i++) { $arg = $lowercase ? strtolower($argv[$i]) : $argv[$i]; $nextarg = $lowercase ? @strtolower($argv[$i+1]) : $argv[$i+1]; $try1 = explode("=",$arg); if(sizeof($try1) > 1) { $key = rmdash($try1[0]); unset($try1[0]); $arga[$key] = implode("=",$try1); } elseif($arg[0] == "-") { $arga[rmdash($arg)] = $nextarg; $i++; } else { $arga[] = $arg; } } } return $arga; } ?>