Prova pratica 2014.05.29

From Sistemi Operativi
Jump to navigation Jump to search

Esercizio 1

Scrivere un programma con un solo parametro.
Come prima cosa il programma deve creare una directory con il path specificato nel parametro. Se la directory esiste gia' o si
verifica un errore nella creazione, il programma deve terminare. Chiameremo questa directory “directory-base”
Il programma usando inotify rimane in attesa e stampa una riga di log per ogni file o directory creato o cancellato nella
directory-base. (solo nella directory-base, non nelle sottodirectory).
Quando viene cancellata la directory-base il programma termina.

Si estenda il programma dell'esercizio 1 per operare anche nelle sottodirectory. Quindi il programma “dovrebbe” stampare una
riga di log per ogni file o directory creata o cancellata in tutto il sottoalbero che ha nella directory-base la radice.
Nota: se necessario, usate strutture dati molto semplici come vettori o liste semplici, non preoccupatevi dell'efficienza.
In realta' per un problema nel design dell'API inotify, alcuni eventi di creazione di directory nidificate troppo vicini nel tempo
possono venir perduti.

Soluzione di Dado

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/inotify.h>


#define EVENT_SIZE (sizeof(struct inotify_event))
#define BUFFER_SIZE (100*(EVENT_SIZE+16))

/*dichiarazione di spy*/
int spy(char *path);

int main(int argc, char * argv[]){
	if(argc!=2){
	printf("Numero argomenti sbagliato\n");
	return -1;
	}else{
		int res=mkdir(argv[1],(mode_t)0777);
		if(res!=0)exit(-1);
		else return spy(argv[1]);
	}
}

/*metodo che utilizza la inotify*/
int spy(char *path){
	int again=1;
	int fd;
	char buffer[BUFFER_SIZE];
	/*inizializzo il File Descriptor dell inotify*/
	fd=inotify_init();
	/*aggiungo "handler" per creazioni, eliminazioni all'interno della cartella path e per la sua eliminazione*/
	inotify_add_watch(fd,path, IN_CREATE | IN_DELETE | IN_DELETE_SELF);
	/*ciclo del programma di attesa dei valori*/
	printf("Entro in ascolto della cartella %s\n",path);
	while(again){
		int i=0;
		int len=read(fd,buffer,BUFFER_SIZE);
		while(i<len){
			/*gestisco un evento alla volta*/
			struct inotify_event *event =(struct inotify_event*)&buffer[i];
				/*controllo eventuale creazione di un file o di una cartella*/
      			if(event->mask & IN_CREATE){
      				/*distinguo i due casi distinti*/
        			if(event->mask & IN_ISDIR){
          				int pid;
          				printf( "Cartella %s creata in %s\n",event->name,path);
          				pid=fork();
          				if(!pid){
          					char *newpath=malloc((strlen(path))+event->len+1); /*sommo 1 alla fine per lo /*/
          					strcpy(newpath,path);
          					strcat(newpath,"/");
          					strcat(newpath,event->name);
          					return spy(newpath);
          				}
        			}
        			else
          				printf("File %s creato in %s\n",event->name,path);
      			}
      			/*controllo eventuale eliminazione di un file o di una cartella*/
      			else if(event->mask & IN_DELETE){
      				/*distinguo i due casi distinti*/
        			if(!(event->mask & IN_ISDIR))
          				printf("File %s eliminato in %s\n",event->name,path);
          		}
          		/*controllo eventuale eliminazione della cartella che sto controllando*/
          		else if(event->mask & IN_DELETE_SELF){
          			printf("Cartella %s eliminata.\n",path);
          			again=0;	/*fermo il ciclo più esterno che esegue le read*/
          		}
          	/*avanzo all'evento successivo, se c'è*/
    		i += EVENT_SIZE + event->len;	
    	}
    }
    return 0;
}

Esercizio 3

Il comando che dovrete implementare come script shell o programma python e' statlen.
Data una directory statlen fa una statistica sulla lunghezza dei nomi dei file presenti in tutto il sottoalbero con radice nella
directory passata come parametro.
es.
$ statlen /tmp
2: 2
3: 10
5: 4
...
significa che in tmp (e in tutte le sottodir.ectory di /tmp) ci sono 2 file con nome di due caratteri, 10 con nomi di 3 caratteri e
cosi' via.

Python3

Soluzione di Krusty

import os, sys
from stat import *

def recScan(pathname,v):
	for f in os.listdir(pathname):
		path = os.path.join(pathname,f)
		s = os.stat(path)
		if S_ISREG(s.st_mode):
			l = len(f)
			if(l not in v):
				v[l]=1
			else:
				v[l] = v[l] + 1
		elif S_ISDIR(s.st_mode):	
			recScan(path,v)

v = {}
recScan(sys.argv[1],v)	
for key in v:
	print(key, ':', v[key])

Bash

Soluzione di ababa

#!/bin/bash
cd $1
files=`find -L`
declare -a stat
for file in $files; do
	file=`basename $file`
	len=`expr length "$file"`
	((stat[$len]++))
done
for i in ${!stat[@]}; do
	echo "${i} : ${stat[$i]}"
done

Mi piacerebbe sapere perché se lo lancio come eseguibile funziona senza problemi se lo lancio con il comando "sh statlen.sh ." invece mi da un sacco di errori.

Perche' "sh" non e' bash ma e' la bourne shell che ha una sitassi meno ricca Renzo (talk) 22:12, 20 April 2015 (CEST)