Comenzaría con el bloqueo del BIOS para que el dispositivo no pueda usarse para iniciar el sistema.
Luego, deshabilitaría el montaje automático para dispositivos USB. En este punto, debe limitar la interacción del usuario con el "subsistema" de la unidad USB. Por ejemplo, esta copia de datos generalmente se requiere para volcar registros o datos adquiridos, por lo tanto, puede reducirlos (en la mayoría de los casos) para:
- monta el dispositivo USB
- verifica que sea válido y que tenga suficiente espacio
- seleccione los datos que desea copiar entre una selección de posibles archivos
(por ejemplo, datalog.001, 20130402-dump.csv, cualquier cosa en / var / local / data ...)
- copiar dichos archivos
- (opcionalmente) releer y verificar sus hashes MD5 / SHA
- (opcionalmente) elimine / gire los originales para liberar espacio en el dispositivo
- desmontar el dispositivo USB
El proceso solo permite la interacción en los "datos seleccionados", y esa interacción está limitada a una opción de casilla de verificación múltiple. Existen utilidades (zenity, kdialog o dialog for curses systems) que le permiten crear una interfaz "bloqueada" en muy poco tiempo: este es un ejemplo adaptado
#!/bin/bash
n=0
for file in $(ls /tmp); do
n=$[n+1]
echo "$file $n off" >> /tmp/output.txt
done
dialog --checklist "Items to copy:" 20 60 20 \
$(cat /tmp/output.txt) 2>/tmp/output2.txt
for i in $(cat /tmp/output2.txt); do
cp $i /mnt/usbkey/
done
rm /tmp/output*
Ahora, el usuario solo puede conectar una llave USB de manera útil cuando el sistema ya se ha iniciado, y cuando lo hace, no sucede nada; cuando elige la función "Volcado de datos", sus opciones son limitadas.
No debería necesitarlo, pero tenga en cuenta las posibles vulnerabilidades a través de metacaracteres de shell incrustados en los nombres de archivos. Siempre obtenga los nombres de los archivos con ls (o equivalente) y filtrelos.
Nota : como lo notó Gilles, el ejemplo anterior es defectuoso: dialog
, solo admitirá nombres sin espacios. Para una implementación más robusta, deberías usar algo más que un script bash, posiblemente Python con Urwid o, dependiendo de la interfaz existente, un CGI o módulo web.
Actualizar
Lo mejor que se puede hacer en bash y con dialog
es, por desgracia, eliminar los archivos problemáticos (aquellos con $, espacio, comilla simple, doble citas...). Un guión mejor, si falta, es este. ignora cualquier archivo que no se adhiera a su convención de nomenclatura; todavía puede ser útil para alguien (por ejemplo, para copiar registros. A menos que ahora esté cerrando data-九月.log
).
#!/bin/bash
DIRTOCOPY="/tmp"
clean() {
rm -f .tmp.dir .tmp.out .tmp.cpy
}
clean
n=0
ls "$DIRTOCOPY" > .tmp.dir
while read file ; do
if ( echo "$file" | grep "^[A-Za-z0-9._~^-]*\$" > /dev/null ); then
n=$[n+1]
echo "$file $n off" >> .tmp.out
fi
done < .tmp.dir
rm -f .tmp.dir
dialog --checklist "Items to copy:" 20 60 20 \
$(cat .tmp.out) 2>.tmp.cpy
cat .tmp.cpy
exit
for file in $( cat .tmp.cpy ); do
echo cp "$file" /mnt/usbkey/
done
clean
Python
Para hacerlo mejor, tenemos que emplear un costructo menos frágil. Como se sugirió anteriormente, esto se puede hacer en Python usando la biblioteca urwid
( apt-get install python-urwid
en Ubuntu, me han dicho. De lo contrario, la instalación es sencilla). Esto es poco más que un tutorial modificado que preparé, pero funciona incluso con archivos que ahogan dialog
o se copian incorrectamente:
/tmp/tests/file with spaces.txt
/tmp/tests/file "quoted, but only once.txt
/tmp/tests/file "quoted twice", that's right!.txt
/tmp/tests/ceci n'est pas une |.txt
Lo único es que los archivos UTF8 pueden tener sus nombres destrozados: tengo un archivo que se llama "Chissà?" en Linux EXT3, y mientras permanece intacto cuando se copia a Linux o NTFS, se convierte en "Chiss ????" (sí, cuatro signos de interrogación) en una llave USB FAT. Pero creo que esto es una limitación del sistema de archivos, no del script.
#!/usr/bin/python
import urwid
from os import listdir
from os.path import isfile, join
from shutil import copyfile
directory = '/tmp'
destination = '/mnt/usbkey'
choices = [ file for file in listdir(directory) if isfile(join(directory,file)) ]
tocopy = [ ]
def menu(title, choices):
body = [urwid.Text(title), urwid.Divider()]
for c in choices:
box = urwid.CheckBox(c, False, False, toggle, c)
body.append(urwid.AttrMap(box, None, focus_map='reversed'))
ende = urwid.Button('-- COPY --')
urwid.connect_signal(ende, 'click', item_chosen)
body.append(urwid.AttrMap(ende, None, focus_map='reversed'))
return urwid.ListBox(urwid.SimpleFocusListWalker(body))
def toggle(button, state, file):
if state:
tocopy.append(file)
else:
tocopy.remove(file)
def item_chosen(button):
response = urwid.Text([u'Proceed with copy?\n'])
done = urwid.Button(u'Proceed')
fine = urwid.Button(u'Cancel')
urwid.connect_signal(done, 'click', copy_files)
urwid.connect_signal(fine, 'click', exit_program)
main.original_widget = urwid.Filler(urwid.Pile([response,
urwid.AttrMap(done, None, focus_map='reversed'),
urwid.AttrMap(fine, None, focus_map='reversed') ]))
def exit_program(button):
raise urwid.ExitMainLoop()
def copy_files(button):
for file in tocopy:
src = join(directory, file)
dst = join(destination, file)
copyfile(src, dst)
raise urwid.ExitMainLoop()
main = urwid.Padding(menu(u'File to be copied to USB', choices), left=2, right=2)
top = urwid.Overlay(main, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9)
urwid.MainLoop(top, palette=[('reversed', 'standout', '')]).run()