diff options
author | Sascha Silbe <sascha-org-sugar-git@silbe.org> | 2009-03-25 22:23:47 (GMT) |
---|---|---|
committer | Sascha Silbe <sascha-org-sugar-git@silbe.org> | 2009-03-25 22:23:47 (GMT) |
commit | 9e945efb04439a31bb3dd9e92b7ebc0ba377c6a0 (patch) | |
tree | 00778e6465cf70301c9c89219b87e343bdeb5ef1 |
first working prototype on a LiveCD
-rw-r--r-- | Xwrapper.config | 2 | ||||
-rwxr-xr-x | build-livecd | 14 | ||||
-rwxr-xr-x | diskmounter.sh | 120 | ||||
-rwxr-xr-x | rc.local | 10 | ||||
-rwxr-xr-x | soas-assimilator.py | 160 |
5 files changed, 306 insertions, 0 deletions
diff --git a/Xwrapper.config b/Xwrapper.config new file mode 100644 index 0000000..ceb83a1 --- /dev/null +++ b/Xwrapper.config @@ -0,0 +1,2 @@ +allowed_users=anybody +nice_value=0 diff --git a/build-livecd b/build-livecd new file mode 100755 index 0000000..51ec753 --- /dev/null +++ b/build-livecd @@ -0,0 +1,14 @@ +#!/bin/bash -e +DEBIAN_MIRROR=http://ftp.de.debian.org/debian/ + +mkdir -p tmp +cd tmp +sudo lh_clean +lh_config -a i386 -d lenny -m "$DEBIAN_MIRROR" --mirror-chroot "$DEBIAN_MIRROR" -p standard-x11 --packages "icewm hal python-dbus python-gobject" +mkdir -p config/chroot_local-includes/{etc/X11,usr/local/bin,/usr/share/initramfs-tools/scripts/live-bottom} +cp ../soas-assimilator.py config/chroot_local-includes/usr/local/bin/ +cp ../diskmounter.sh config/chroot_local-includes/usr/local/bin/ +cp ../rc.local config/chroot_local-includes/etc/ +cp ../Xwrapper.config config/chroot_local-includes/etc/X11/ +sudo lh_build + diff --git a/diskmounter.sh b/diskmounter.sh new file mode 100755 index 0000000..023e272 --- /dev/null +++ b/diskmounter.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# +# This utility searches for available HFS+, NTFS, FAT32 and various Linux +# partitions, creates mount points for them and adds them to /etc/fstab. +# +# -- +# +# (c)2008 pure:dyne team <puredyne-team@goto10.org> +# (c)2005 Dennis Kaarsemaker <dennis@ubuntu-nl.org> +# Thanks to Nalioth for suggesting, assisting with and testing the HFS+ bits +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# -- + +# Root check +if [[ $UID != 0 ]]; then + echo 'You should run this program as root or using sudo' + exit 1 +fi + +# Simple command line argument for installers +# -w: mount them with user,umask=0111 +# -r: mount them with user,umask=0133,uid=1000,gid=1000 +RWALL=-1; +if [[ $1 == '-w' ]]; then RWALL=1; fi +if [[ $1 == '-r' ]]; then RWALL=0; fi + +if [[ $RWALL == -1 ]]; then + echo 'By default the disks will be writable only by root and' + cat /etc/passwd | awk -F ':|,' '/:1000:/ {print $5 " (" $1 ")"}' + echo 'Do you want to make the disk writable by all users instead? (y/n)' + read RESP + if [[ $RESP == 'y' || $RESP == 'Y' ]]; then + RWALL=1 + else + RWALL=0 + fi +fi + +if [[ $RWALL == 1 ]]; then + OPTIONS='user,fmask=0111,dmask=0000' + MACOPTIONS='user,file_umask=0111,dir_umask=0000' +else + OPTIONS='user,fmask=0133,dmask=0022,uid=1000,gid=1000' + MACOPTIONS='user,file_umask=0133,dir_umask=0022,uid=1000,gid=1000' +fi + +# FS detection +drivesntfs=`fdisk -l | grep -i 'ntfs' | awk -F '/| ' '{print $3}'` +drivesfat=`fdisk -l | grep -i 'fat32' | awk -F '/| ' '{print $3}'` +driveshfs=`fdisk -l | grep -i 'af' | awk -F '/| ' '{print $3}'` +drivelinux=`fdisk -l | grep -i 'Linux' | grep -v 'swap' | awk -F '/| ' '{print $3}'` + +donesomething='n' + +# fstab populating +for drive in $drivesntfs; do + if [[ ! `grep $drive /etc/fstab` ]]; then + mkdir "/media/$drive" + echo "/dev/$drive /media/$drive ntfs-3g 0 0" >> /etc/fstab + echo "Added /dev/$drive as '/media/$drive' (read-only)" + donesomething='y' + else + echo "Ignoring /dev/$drive - already in /etc/fstab" + fi +done + +for drive in $drivesfat; do + if [[ ! `grep $drive /etc/fstab` ]]; then + mkdir "/media/$drive" + echo "/dev/$drive /media/$drive vfat rw,$OPTIONS 0 0" >> /etc/fstab + echo "Added /dev/$drive as '/media/$drive'" + donesomething='y' + else + echo "Ignoring /dev/$drive - already in /etc/fstab" + fi +done + +for drive in $driveshfs; do + if [[ ! `grep $drive /etc/fstab` ]]; then + mkdir "/media/$drive" + echo "/dev/$drive /media/$drive hfsplus rw,$MACOPTIONS 0 0" >> /etc/fstab + echo "Added /dev/$drive as '/media/$drive'" + donesomething='y' + else + echo "Ignoring /dev/$drive - already in /etc/fstab" + fi +done + +for drive in $drivelinux; do + if [[ ! `grep $drive /etc/fstab` ]]; then + mkdir "/media/$drive" + echo "/dev/$drive /media/$drive auto defaults 0 0" >> /etc/fstab + echo "Added /dev/$drive as '/media/$drive'" + donesomething='y' + else + echo "Ignoring /dev/$drive - already in /etc/fstab" + fi +done + +if [[ $donesomething == 'y' ]]; then + # And mount them + echo "Mounting the partitions now..." + mount -a +else + echo "No usable partitions found..." +fi diff --git a/rc.local b/rc.local new file mode 100755 index 0000000..39128c9 --- /dev/null +++ b/rc.local @@ -0,0 +1,10 @@ +#!/bin/bash -e +# rc.local +# This script is executed at the end of each multiuser runlevel. + +# Detect partitions (non-swap) and mount them +# See /usr/local/bin/diskmounter.sh for supported filesystems +/usr/local/bin/diskmounter.sh -w + +sudo -u user -H startx + diff --git a/soas-assimilator.py b/soas-assimilator.py new file mode 100755 index 0000000..37106f9 --- /dev/null +++ b/soas-assimilator.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +import os +import shutil +import sys +import time +import threading +import traceback +import dbus +import dbus.mainloop.glib +import gobject + + +class Logger (object) : + + def __init__(self) : + self._lock = threading.Lock() + + def start(self, image_path, dev_path, model) : + self._print("%s: starting to write %s on %s" % (dev_path, image_path, model)) + + def error(self, dev_path, exc) : + self._print("%s: aborted with error: %s" % (dev_path, exc)) + + def success(self, dev_path, time_delta, size) : + self._print("%s: finished successfully (%ds, %.3fMB/s)" % (dev_path, + time_delta,float(size)/1024/1024/time_delta)) + + def _print(self, msg) : + self._lock.acquire() + try : + print msg + + finally : + self._lock.release() + + +class CopyThread (threading.Thread) : + + def __init__(self, image_path, dev_path, model, size, logger) : + threading.Thread.__init__(self) + self.image_path = image_path + self.dev_path = dev_path + self.model = model + self.size = size + self.logger = logger + + def run(self) : + self.start_time = time.time() + self.logger.start(self.image_path, self.dev_path, self.model) + try : + shutil.copyfileobj(file(self.image_path, "rb"), file(self.dev_path, "wb")) + + except : + self.logger.error(self.dev_path, sys.exc_info()[1]) + + else : + self.logger.success(self.dev_path, time.time() - self.start_time, self.size) + + +class DeviceListener (object) : + + def __init__(self, image_prefix) : + self.image_prefix = image_prefix + self.logger = Logger() + self._images_dict = {} + self._images_flat = [] + self._images_lastupdate = 0 + self.bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) + self.bus.add_signal_receiver(self.hal_device_added, + "DeviceAdded", + "org.freedesktop.Hal.Manager", + "org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager") + + def run(self) : + gobject.MainLoop().run() + + def hal_device_added(self, udi) : + try : + proxy = self.bus.get_object("org.freedesktop.Hal", udi) + dev = dbus.Interface(proxy, "org.freedesktop.Hal.Device") + props = dev.GetAllProperties() + if (props.get("info.category") != "storage") \ + or (props.get("storage.removable") != 1) \ + or (props.get("storage.drive_type") != "disk") : + # not a USB stick + return + + # for debugging +# for (k,v) in props.items() : +# print "%30s %s" % (k,v) + + self.assimilate(str(props['storage.model']), str(props['block.device']), + int(props['storage.removable.media_size'])) + + except : + # don't break if we have trouble with a single device, but show the error + traceback.print_exc() + + def assimilate(self, model, dev_path, size) : +# image_path = "%s-%s.img" % (self.image_prefix, self._format_size(size)) + image_path = self._find_image(size) + thread = CopyThread(image_path, dev_path, model, size, self.logger) + thread.start() + + _sizeUnits = "KMGTP" + def _format_size(self, size) : + if not size : + return "0" + + unitIdx = 0 + while ((size % 1024) == 0) : + size //= 1024 + unitIdx += 1 + + return "%d%s" % (size, self._sizeUnits[unitIdx]) + + def _find_image(self, size) : + """ + Try to find image to put on current stick. Will return the largest one + still fitting on the stick. + """ + self._cache_images() + return [iname for (isize, iname) in self._images_flat if (isize <= size)][-1] + + + _images_cachetime = 10 # rescan images every 10 seconds + def _cache_images(self) : + curTime = time.time() + if (curTime - self._images_lastupdate) < self._images_cachetime : + return + + image_names = [fname for fname in os.listdir(".") if fname.startswith(self.image_prefix) and fname.endswith(".img")] + for name in image_names : + if name not in self._images_dict : + self._images_dict[os.stat(name).st_size] = name + self._images_flat = sorted(self._images_dict.items()) + + self._images_lastupdate = curTime + + + +def printSyntax(myName) : + print "Syntax: %s <image prefix>" % (myName,) + print "Sample: %s Soas-20090324" % (myName,) + return 100 + +def main(myName, args) : + if (len(args) < 1) : + return printSyntax(myName) + + image_prefix, = args + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + gobject.threads_init() + DeviceListener(image_prefix).run() + +if __name__ == '__main__' : + sys.exit(main(sys.argv[0], sys.argv[1:])) + |