Solucion

Anuncio
Examen de Fundamentos de Sistemas Operativos
Tiempo total: 2.5 horas.
Problema: Llamadas al sistema (7 puntos)
Implemente un programa similar a tee(1) que descomprima los datos que lee de la entrada estándar. Una
invocación sería como sigue:
; ztee fichsalida < fichentrada
El programa debe leer de su entrada estándar datos comprimidos con gzip(1) sin ningún argumento, y debe
escribir los datos descomprimidos por su salida estándar. Para descomprimirlos puede ejecutar gunzip(1).
Además, el programa debe escribir lo mismo, es decir, el resultado de descomprimir los datos por su salida
estándar, en el fichero que recibe como parámetro. Naturalmente, no se permite la utlización del comando
tee(1) ni el uso de ficheros temporales.
Entrega: Copie un fichero llamado ztee-login.c, donde login es tu nombre de usuario, en el directorio /usr/elf/examen. ATENCIÓN: Sólo se puede efectuar la entrega una vez. Ponga un comentario con su nombre y apellidos en el fichero.
-2-
Solución

ztee.c 
______
#include <u.h>
#include <libc.h>
enum {
Blen = 256,
};
static void
usage(void)
{
fprint(2, "usage: %s outfile\n", argv0);
exits("usage");
}
void
main(int argc, char *argv[])
{
int fd;
int p[2];
long len;
char buf[Blen];
ARGBEGIN{
default:
usage();
}ARGEND
if(argc != 1)
usage();
if(pipe(p) < 0)
sysfatal("pipe: %r");
switch(fork()){
case -1:
sysfatal("fork: %r");
case 0:
dup(p[1], 1);
close(p[1]);
close(p[0]);
execl("/bin/gunzip", "gunzip", "-v", nil);
sysfatal("exec failed");
}
fd = create(argv[0], OWRITE, 0664);
if(fd < 0)
sysfatal("create: %s: %r", argv[0]);
close(p[1]);
-3-
while((len = read(p[0], buf, Blen)) > 0){
if(write(fd, buf, len) != len)
sysfatal("%s: write: %r", argv[0]);
if(write(1, buf, len) != len)
sysfatal("stdout: write: %r");
}
if(len < 0)
sysfatal("pipe read: %r");
close(p[0]);
close(fd);
waitpid();
exits(nil);
}
Problema: Shell Script (3 puntos)
Escriba un script de RC llamado listfiles.rc que reciba un número indeterminado de argumentos
indicando ‘‘extensiones’’ de ficheros (parte del nombre después del último punto). El programa debe
escribir por su salida estándar la lista de todos los ficheros con dicha ‘‘extensión’’ del $home del usuario
que tienen permiso de lectura para todos los usuarios, ordenados alfabéticamente y sin elementos duplicados. Por ejemplo, esta podría ser una ejecución del programa:
; listfiles jpg pdf doc
/usr/pepe/doc/tesis/figuras/mouse.jpg
/usr/pepe/doc/tesis/figuras/sdcard.jpg
/usr/pepe/doc/tesis/figuras/tft.jpg
/usr/pepe/doc/tesis/figuras/xw9300.jpg
/usr/pepe/doc/tesis/portada.pdf
/usr/pepe/doc/tesis/presentacion/presentacion.pdf
/usr/pepe/doc/var/cartel_puerta.pdf
/usr/pepe/doc/www/03.sec-auth.pdf
/usr/pepe/doc/www/04.sec-malware.pdf
/usr/pepe/tmp/a.doc
/usr/pepe/tmp/all.pdf
/usr/pepe/tmp/e.pdf
Entrega: Copie un fichero llamado listfiles-login.rc, donde login es tu nombre de usuario, en el
directorio /usr/elf/examen. ATENCIÓN: Sólo se puede efectuar la entrega una vez. Ponga un
comentario con su nombre y apellidos en el fichero.
-4-
Solución
Hay muchas soluciones posibles. Una solución sencilla pero mejorable es la siguiente:
__________
listfiles2.rc 

#!/bin/rc
if(~ $#* 0){
echo "usage: listfiles ext ..." >[1=2]
exit usage
}
test -f /tmp/aux && rm /tmp/aux >[2] /dev/null
for(i in ‘{du -a $home >[2] /dev/null | awk ’{print $2}’}){
ext=‘{echo $i | sed ’s/.*\.(.*)$/\1/’}
if(~ $ext $*){
ls -l $i | grep ’^[^d].......r..’ | awk ’{print $10}’ >> /tmp/aux
}
}
sort -u /tmp/aux >[2] /dev/null
rm /tmp/aux >[2] /dev/null
exit ’’
El comando du -a no nos da la salida en un orden alfabético ASCII estricto (dado que se recorre el árbol
en profundidad, puede desordenar nombres de fichero que comiencen con un símbolo de puntuación). Por
esa razón, para cumplir con el enunciado de forma precisa, ordenando y eliminando duplicados (que
también se pueden dar en directorios unión, aunque sea un caso raro), ejecutaremos sort sobre un fichero
temporal que usamos para almacenar la lista de ficheros que cumplen con los requisitos indicados.
Para simplificar, no hacemos que el nombre del fichero temporal sea único para cada ejecución.
Esta primera versión es claramente mejorable. En realidad, nos podemos ahorrar el fichero temporal.
También podemos prescindir del pipeline usado para conseguir la ‘‘extensión’’ del nombre del fichero,
usando el comando ˜ directamente:
__________
listfiles3.rc 

#!/bin/rc
if(~ $#* 0){
echo "usage: listfiles ext ..." >[1=2]
exit usage
}
for(i in ‘{du -a $home >[2] /dev/null | awk ’{print $2}’ | sort -u }){
if(~ $i *.$*){
ls -l $i | grep ’^[^d].......r..’ | awk ’{print $10}’
}
}
exit ’’
Otra solución podría ser la siguiente, en la que componemos una expresión regular a partir de los argumentos para filtrar los ficheros por su ‘‘extensión’’:
_________
listfiles.rc 

#!/bin/rc
-5-
if(~ $#* 0){
echo "usage: listfiles ext ..." >[1=2]
exit usage
}
regexpr=’\.(’^‘{echo $* | tr ’ ’
’|’}^’)$’
{for(i in ‘{du -a $home >[2] /dev/null | grep $"regexpr | awk ’{print $2}’ }){
if(ls -l $i | grep -s ’^[^d].......r..’){
echo $i
}
}} | sort -u
Descargar