On the server:
fetchnew.php:
#!/usr/bin/env php
<?php
$url = "http://www.secondlife.com/community/linux-alpha.php";
$tmpfp = tmpfile();
//$url = "http://www.cyberleo.net/cyberleo/Downloads/SecondLife_i686_1_18_1_2.tar.bz2";
//$tmpfp = fopen("/home/cyberleo/secondlife/SecondLife_i686_1_18_0_6.tar.bz2", "r");
$stage = sprintf("%s/%s", "/home/cyberleo/secondlife/tmp", md5(time()+microtime()));
$target = "/home/cyberleo/secondlife/linux";
$pointer = "/home/cyberleo/secondlife/linux/SecondLife";
$ptrfp = fopen($pointer, "w");
if (!flock($ptrfp, LOCK_EX | LOCK_NB, $wouldblock) && $wouldblock)
die("Already running.\n");
// Create temp directory
if (!mkdir($stage))
die("Directory race!\n");
$useful = file($url);
// Extract the most useful line
$useful = preg_grep("/\.tar\.bz2.*Linux i686/", $useful);
// Extract the most useful URL from that line
$useful = array_values($useful);
$useful = $useful[0];
$useful = preg_split("/\"(http:\/\/.*\.tar\.bz2)\".*Linux i686\<\/a\>: ([^ ]+)/", $useful, -1, PREG_SPLIT_DELIM_CAPTURE);
$url = $useful[1];
$version = $useful[2];
if (!$url)
die("Didn't get a valid URL! Help!");
$components = parse_url($url);
printf("Fetching version %s from %s...\n", $version, $components['host']);
unset($useful);
unset($components);
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, "MyBrowse/1.0 (GS/OS 6.0.3; AppleIIgs)");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
//curl_setopt($curl, CURLOPT_MUTE, TRUE);
curl_setopt($curl, CURLOPT_NOPROGRESS, FALSE);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_FILE, $tmpfp);
curl_exec($curl);
curl_close($curl);
$length = fstat($tmpfp);
$length = $length['size'];
// Set up command environment
$command = sprintf("/usr/bin/nice -n 10 /usr/bin/tar jxvCf %s - 2>&1", escapeshellarg($stage));
$pipes = Array(
0 => Array("pipe", "r"),
1 => Array("pipe", "w"),
2 => Array("pipe", "w")
);
$cmdfp = proc_open($command, $pipes, $pipes, $stage);
if (!is_resource($cmdfp))
die("proc_open failed.\n");
if (!is_resource($pipes[0])) {
var_dump($pipes);
die("stdin isn't a pipe!\n");
}
stream_set_blocking($pipes[0], FALSE);
stream_set_blocking($pipes[1], FALSE);
echo "Extracting...\n";
fseek($tmpfp, 0);
$count = 0;
$f_len = strlen($length);
$fmt = sprintf(' %%%1$uu / %%%1$uu (%%3u%%%%) %%s '."\033[K\r", $f_len);
sprintf($fmt, $count, $length, (100 * ($count / $length)), "");
$time = $oldtime = time();
$bufr = "";
while(!feof($tmpfp) || strlen($bufr)) {
if (strlen($bufr) < 512)
$bufr.= fread($tmpfp, 65536);
$read = Array($pipes[1]);
$write = Array($pipes[0]);
$except = NULL;
if (stream_select($read, $write, $except, 1)) {
if ($read) {
while ($tmp = fgets($pipes[1], 4096))
$curout = $tmp;
}
if ($write) {
$len = fwrite($pipes[0], $bufr, strlen($bufr));
if ($len)
$bufr = substr($bufr, $len, strlen($bufr) - $len);
$count+= $len;
}
}
if (time() != $time) {
printf($fmt, $count, $length, (100 * ($count / $length)),
sprintf("...%s", substr(trim($curout), -45, 45)));
$oldtime = $time;
$time = time();
}
}
printf($fmt, $count, $length, (100 * ($count / $length)), "");
echo "\n";
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$result = proc_close($cmdfp);
fclose($tmpfp);
unset($count, $length);
unset($fmt);
unset($time, $oldtime);
unset($bufr, $read, $write);
unset($command);
if ($result !== 0) {
var_dump($curout);
die("Something failed!\n");
}
echo "Moving into place...\n";
$name = trim(shell_exec(sprintf("ls -1 %s", escapeshellarg($stage))));
$src = sprintf("%s/%s", $stage, $name);
$dst = sprintf("%s/%s", $target, $name);
shell_exec(sprintf("/bin/rm -Rf %s", escapeshellarg($dst)));
rename($src, $dst);
shell_exec(sprintf("/bin/rm -Rf %s", escapeshellarg($stage)));
fwrite($ptrfp, $name, strlen($name));
fwrite($ptrfp, "\n", 1);
flock($ptrfp, LOCK_UN);
fclose($ptrfp);
/*
fclose($dstfp);
echo "Extracting...\n";
$command = sprintf("/usr/bin/nice -n 10 /usr/bin/tar jxCf %s %s", escapeshellarg($target), escapeshellarg($dstfile));
var_dump($command);
var_dump(shell_exec($command));
unlink($dstfile);
*/
On the client: updatesl.sh:
#!/bin/bash mkdir -p tmp echo "Fetching pointer..." rsync --compress --progress --stats rsync://cyberleo@pizzabox:~/secondlife/linux/SecondLife ./tmp/pointer if [ "$?" -ne 0 -o ! -f ./tmp/pointer ] then echo "Pointer fetch failed." exit 64 fi pointer="$(cat ./tmp/pointer)" echo "Got pointer to ${pointer}" if [ -e "${pointer}" ] then echo "Destination directory ${pointer} already exists." exit 32 fi cur="$( stat -c "%N" SecondLife | cut -d' ' -f3 | tr -d '`/'\' )" echo "Updating ${cur} -> ${pointer}" cp -pR "${cur}" "${pointer}" if [ "$?" -ne 0 ] then echo "Tree clone failed." exit 16 fi rsync --archive --compress --delete --hard-links --progress --sparse --stats "rsync://cyberleo@pizzabox:~/secondlife/linux/${pointer}" "./${pointer}" if [ "$?" -ne 0 ] then echo "rsync failed." exit 8 fi echo "Linking" rm -f SecondLife ln -svf "${pointer}" SecondLife rm tmp/pointer echo "Done."