Difference between revisions of "ProvaPratica 2013.06.21"
m (Aggiunte soluzioni da altre pagine) |
|||
(34 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
+ | == Esercizio 1 == | ||
+ | ===Soluzione di Tommaso Ognibene=== | ||
+ | <syntaxhighlight lang="C"> | ||
+ | /* | ||
+ | Prova Pratica di Laboratorio di Sistemi Operativi | ||
+ | 20 giugno 2013 | ||
+ | Esercizio 1 | ||
+ | |||
+ | URL: http://www.cs.unibo.it/~renzo/so/pratiche/2013.06.21.pdf | ||
+ | |||
+ | @author: Tommaso Ognibene | ||
+ | */ | ||
+ | |||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <dirent.h> | ||
+ | #include <errno.h> | ||
+ | #include <unistd.h> | ||
+ | |||
+ | /* Comparison function for iNode | ||
+ | * Input: 2 dirent pointers | ||
+ | * Output: | ||
+ | * 1, if iNode[a] > iNode[b] | ||
+ | * 0, if iNode[a] == iNode[b] | ||
+ | * -1, else */ | ||
+ | int iNodeComparison(const struct dirent **a, const struct dirent **b) | ||
+ | { | ||
+ | long iNodeA = (long)(*a)->d_ino; | ||
+ | long iNodeB = (long)(*b)->d_ino; | ||
+ | return (iNodeA > iNodeB) - (iNodeA < iNodeB); | ||
+ | } | ||
+ | |||
+ | /* Scan a directory -> | ||
+ | * Order the entries by iNode number -> | ||
+ | * Print name and iNode of each file. */ | ||
+ | void scanDirectory(char *dir) | ||
+ | { | ||
+ | int result, iterator; | ||
+ | struct dirent **files; | ||
+ | |||
+ | result = scandir(dir, &files, NULL, iNodeComparison); | ||
+ | |||
+ | // Check if any errors occurred | ||
+ | if (result < 0) | ||
+ | { | ||
+ | perror("scandir()"); | ||
+ | exit(EXIT_FAILURE); | ||
+ | } | ||
+ | |||
+ | // Loop through directory entries | ||
+ | for(iterator = 0; iterator < result; iterator++) | ||
+ | { | ||
+ | printf("%s/%s %li\n", dir, files[iterator]->d_name, (long)files[iterator]->d_ino); | ||
+ | |||
+ | // Garbage collection | ||
+ | free(files[iterator]); | ||
+ | } | ||
+ | free(files); | ||
+ | } | ||
+ | |||
+ | // Entry point | ||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | char cwd[1024]; | ||
+ | |||
+ | // if (number of parameters | ||
+ | switch(argc) | ||
+ | { | ||
+ | // == 0) => Use the current directory | ||
+ | case 1: | ||
+ | if (!getcwd(cwd, sizeof(cwd))) | ||
+ | { | ||
+ | perror("getcwd()"); | ||
+ | exit(EXIT_FAILURE); | ||
+ | } | ||
+ | scanDirectory(cwd); | ||
+ | exit(EXIT_SUCCESS); | ||
+ | |||
+ | // == 1) => Use the given directory | ||
+ | case 2: | ||
+ | scanDirectory(argv[1]); | ||
+ | exit(EXIT_SUCCESS); | ||
+ | |||
+ | // > 1) => Wrong input | ||
+ | default: | ||
+ | printf("The function requires 0 or 1 parameters.\n"); | ||
+ | exit(EXIT_FAILURE); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Soluzione di Giulia N.=== | ||
+ | |||
+ | La mia versione: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | /*Scrivere un programma che stampi il numero di inode di ogni file presente in una direcotory passata come argomento (o della | ||
+ | direcotry corrente se il programma viene chiamato senza parametri) e stampi l'elenco in ordine crescente di numero di i-node. | ||
+ | Es: | ||
+ | $ lsino demo | ||
+ | demo/. 1972484 | ||
+ | demo/.. 1971834 | ||
+ | demo/1.c 1972528 | ||
+ | demo/a.out 1972485 | ||
+ | demo/l1 1972486 | ||
+ | demo/l2 1972486 | ||
+ | demo/l3 1972486 | ||
+ | demo/link.c 1972528*/ | ||
+ | |||
+ | #define _SVID_SOURCE | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <unistd.h> | ||
+ | #include <errno.h> | ||
+ | #include <dirent.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | int main(int argc, char *argv[]){ | ||
+ | struct stat sb; | ||
+ | char cwd[1024]; | ||
+ | struct dirent **namelist; | ||
+ | int n; /*valore di ritorno di scandir*/ | ||
+ | int i=0; | ||
+ | |||
+ | if(argc>1){ /*se la directory e' stata data in input*/ | ||
+ | strcpy(cwd,argv[1]); | ||
+ | } | ||
+ | else{ /*se la directory non viene data in input*/ | ||
+ | getcwd(cwd, sizeof(cwd)); | ||
+ | } | ||
+ | /*ora dentro cwd c'è la cartella interessata*/ | ||
+ | |||
+ | n = scandir(cwd, &namelist, NULL, alphasort); | ||
+ | |||
+ | if(n<0) | ||
+ | perror("scandir"); | ||
+ | else { | ||
+ | while (i<n) { | ||
+ | printf("%s/%s %ld\n", cwd,namelist[i]->d_name,(long)namelist[i]->d_ino); | ||
+ | free(namelist[i]); | ||
+ | i++; | ||
+ | } | ||
+ | free(namelist); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | Non mi è chiara una cosa: nel testo specifica "stampi l'elenco in ordine crescente di numero di i-node", tuttavia nell'esempio sono ordinati grazie a quella che penso sia l'alphasort e quindi è la soluzione che ho sviluppato io. | ||
+ | Giulia N. | ||
+ | |||
+ | ===Soluzione di D.Boldrin=== | ||
+ | <source lang="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <dirent.h> | ||
+ | |||
+ | typedef struct listnode { //struttura dati per contenere tutti gli inode dei file di una directory | ||
+ | struct listnode *next; | ||
+ | int inode; | ||
+ | }listnode; | ||
+ | |||
+ | int main(int argc, char* argv[]){ | ||
+ | struct stat fileStat; | ||
+ | int contanode=0; | ||
+ | char *filename=argv[1]; | ||
+ | struct stat tp; | ||
+ | DIR *path; | ||
+ | struct dirent *dir_object; | ||
+ | path = opendir(argv[1]); | ||
+ | |||
+ | |||
+ | listnode *root; | ||
+ | root = (listnode*)calloc(1, sizeof(listnode)); | ||
+ | listnode *tmp=root; | ||
+ | dir_object = readdir(path); //comincia la scansione della cartella | ||
+ | while(dir_object != NULL){ | ||
+ | |||
+ | stat(dir_object->d_name, &tp); | ||
+ | if (S_ISREG(tp.st_mode)){ //l'oggetto dir_object é un file,quindi lo salvo nella struttura | ||
+ | contanode++; | ||
+ | stat(dir_object->d_name, &fileStat); | ||
+ | tmp->inode=(fileStat.st_ino); | ||
+ | tmp->next=(listnode*)calloc(1, sizeof(listnode)); | ||
+ | tmp=tmp->next; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | dir_object = readdir(path); | ||
+ | } | ||
+ | |||
+ | |||
+ | printf("%d\n", contanode); | ||
+ | ordinaLista(root); | ||
+ | stampaLista(root); | ||
+ | } | ||
+ | |||
+ | |||
+ | void ordinaLista(listnode *pnt){ | ||
+ | |||
+ | listnode *tmp=pnt; | ||
+ | int temp; | ||
+ | while(tmp->next!=NULL){ | ||
+ | |||
+ | while(pnt->next!=NULL){ | ||
+ | if(pnt->inode<tmp->inode){ | ||
+ | temp=pnt->inode; | ||
+ | pnt->inode=tmp->inode; | ||
+ | tmp->inode=temp; | ||
+ | } | ||
+ | else{ | ||
+ | pnt=pnt->next; | ||
+ | } | ||
+ | } | ||
+ | tmp=tmp->next; | ||
+ | pnt=tmp; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void stampaLista(listnode *pnt){ | ||
+ | |||
+ | while(pnt->next!=NULL){ | ||
+ | printf("%d\n",pnt->inode); | ||
+ | pnt=pnt->next; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Problema: Se come parametro gli passo l'indirizzo di una directory diverso da quella in cui si trova il file.c, non funziona, o meglio esegue, termina ma non trova alcun file all'interno della directory (anche se sono sicuro che i file ci sono). | ||
+ | |||
+ | |||
+ | === Soluzione di blissett === | ||
+ | <source lang="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <dirent.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <unistd.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | |||
+ | #define MAX 1000 | ||
+ | |||
+ | |||
+ | /* struttura che salvera nome e i_node di ogni file presente nella directory */ | ||
+ | typedef struct i_node { | ||
+ | int num; | ||
+ | char *nome; | ||
+ | }i_node; | ||
+ | |||
+ | |||
+ | static int confronto (i_node* elem1, i_node* elem2) | ||
+ | { | ||
+ | return (elem1->num - elem2->num); | ||
+ | } | ||
+ | |||
+ | |||
+ | int main (int argc, char *argv[]) | ||
+ | { | ||
+ | int x=0; | ||
+ | int y=0; | ||
+ | DIR *root; | ||
+ | char *buf=malloc (100*(sizeof(char))); | ||
+ | struct dirent *d; | ||
+ | i_node A[MAX]; | ||
+ | |||
+ | if (argv[1]==NULL) | ||
+ | { | ||
+ | |||
+ | getcwd(buf, MAX); /* prendo directory corrente e la salvo in buf */ | ||
+ | if ((root = opendir (buf)) == NULL) | ||
+ | { | ||
+ | perror("opendir"); | ||
+ | return -1; | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | buf =argv[1]; | ||
+ | if ((root = opendir (buf)) == NULL) | ||
+ | { | ||
+ | perror("opendir"); | ||
+ | return -1; | ||
+ | } | ||
+ | chdir(buf); /*cambio directory corrente con quella passato a linea di comando*/ | ||
+ | } | ||
+ | |||
+ | |||
+ | /* SE VOGLIO STAMPARE SOLO I FILE REGOLARI | ||
+ | while ((d=readdir (root))!=NULL) | ||
+ | { | ||
+ | stat(d->d_name,&f); | ||
+ | if (S_ISREG(f.st_mode)) | ||
+ | { | ||
+ | A[x].nome = d->d_name; | ||
+ | A[x].nodo = d->d_ino; | ||
+ | x++; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | */ | ||
+ | |||
+ | |||
+ | /* scorro tutta la directory */ | ||
+ | while ((d=readdir (root))!=NULL) | ||
+ | { | ||
+ | A[x].nome = d->d_name; | ||
+ | A[x].num = d->d_ino; | ||
+ | x++; | ||
+ | } | ||
+ | |||
+ | qsort(A, x--, sizeof(i_node), confronto); /* riodina seguendo la funzione "confronto" */ | ||
+ | |||
+ | while (y<=x) | ||
+ | { | ||
+ | printf ("\n/%s ------ %d \n", A[y].nome, A[y].num); | ||
+ | y++; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | --[[User:Blissett|Blissett]] ([[User talk:Blissett|talk]]) 09:36, 18 March 2015 (CET) | ||
+ | |||
+ | == Esercizio 2 == | ||
+ | ===Soluzione di Alessandro C.=== | ||
+ | <syntaxhighlight lang ="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | #include <dirent.h> | ||
+ | #define PATH_SIZE 1024 | ||
+ | |||
+ | int iNoSort(const struct dirent** dir1, const struct dirent** dir2){ | ||
+ | int a = (*dir1)->d_ino; | ||
+ | int b = (*dir2)->d_ino; | ||
+ | if (a<b) return -1; | ||
+ | else if (a>b) return 1; | ||
+ | else return 0; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char** argv){ | ||
+ | struct dirent** namelist; | ||
+ | int n, i, j; | ||
+ | int link = 0; | ||
+ | char path[PATH_SIZE]; | ||
+ | if (argc == 1) {strcpy(path, "./");} | ||
+ | else if (argc == 2) {strcpy(path, argv[1]);} | ||
+ | n = scandir(path, &namelist, NULL, iNoSort); | ||
+ | if (n == -1) {perror("scandir"); exit(1);} | ||
+ | for (i=0; i<n; i++){ | ||
+ | //printf("%s%s %d\n", path, namelist[i]->d_name, (int) namelist[i]->d_ino); | ||
+ | if (namelist[i]->d_ino == 0) continue; | ||
+ | for(j = i+1; j<n; j++){ | ||
+ | if (namelist[j]->d_ino == namelist[i]->d_ino){ | ||
+ | if (link == 0) {printf("%s ", namelist[i]->d_name); link++;} | ||
+ | printf("%s ",namelist[j]->d_name); | ||
+ | namelist[j]->d_ino = 0; | ||
+ | } | ||
+ | } | ||
+ | if(link > 0) printf("\n"); | ||
+ | link = 0; | ||
+ | } | ||
+ | return 1; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Alessandro C. | ||
+ | |||
+ | == Esercizio 3 == | ||
+ | ===Soluzione di Tommaso Ognibene=== | ||
[Python 3] | [Python 3] | ||
Line 26: | Line 402: | ||
# Build a dictionary with key-value pair {MD5 hash - [file name]} | # Build a dictionary with key-value pair {MD5 hash - [file name]} | ||
sameContent = { } | sameContent = { } | ||
− | for | + | for filePaths in sorted(sameSize.values(), key = len, reverse = True): |
− | if len( | + | # No files with same size => No files with same content |
− | + | if len(filePaths) < 2: break | |
− | PopulateSameContent( | + | PopulateSameContent(filePaths, sameContent) |
# Print results | # Print results | ||
Line 36: | Line 412: | ||
print("Done!") | print("Done!") | ||
− | # Populate a dictionary with key-value pair {file size - file name} | + | # Populate a dictionary with key-value pair {file size - [file name]} |
def PopulateSameSize(sameSize): | def PopulateSameSize(sameSize): | ||
− | for dirPath, | + | for dirPath, _, fileNames in os.walk(os.getcwd()): |
for fileName in fileNames: | for fileName in fileNames: | ||
filePath = os.path.join(dirPath, fileName) | filePath = os.path.join(dirPath, fileName) | ||
Line 44: | Line 420: | ||
sameSize[fileSize] = sameSize.get(fileSize, []) + [filePath] | sameSize[fileSize] = sameSize.get(fileSize, []) + [filePath] | ||
− | # | + | # Populate a dictionary with key-value pair {MD5 hash - [file name]} |
− | def PopulateSameContent( | + | def PopulateSameContent(filePaths, sameContent): |
− | for filePath in | + | for filePath in filePaths: |
− | md5 = | + | md5 = GetMd5Hash(filePath) |
fileRelPath = os.path.relpath(filePath, os.getcwd()) | fileRelPath = os.path.relpath(filePath, os.getcwd()) | ||
sameContent[md5] = sameContent.get(md5, []) + [fileRelPath] | sameContent[md5] = sameContent.get(md5, []) + [fileRelPath] | ||
− | # | + | # Get the MD5 hash without loading the whole file to memory |
− | def | + | # Break the file in chunks whose size is a multiple of 128 |
− | with open(filePath, | + | # This takes advantage of the fact that MD5 has 128-byte digest blocks |
− | + | def GetMd5Hash(filePath, blockSize = 2 ** 20): | |
− | + | digest = hashlib.md5() | |
− | + | with open(filePath, "rb") as file: | |
− | + | for chunk in iter(lambda: file.read(blockSize), b''): | |
− | + | digest.update(chunk) | |
− | + | return digest.hexdigest() | |
− | |||
# Printout the lists of files having same content | # Printout the lists of files having same content | ||
def PrintResults(sameContent): | def PrintResults(sameContent): | ||
− | print( | + | print("Lists of files having same content:") |
− | for | + | for files in sorted(sameContent.values(), key = len, reverse = True): |
− | if len( | + | if len(files) < 2: break |
− | + | print("[{0}]".format(", ".join(file for file in files))) | |
if __name__ == "__main__": | if __name__ == "__main__": | ||
sys.exit(Main(sys.argv)) | sys.exit(Main(sys.argv)) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | ===Soluzione di Fede=== | ||
+ | |||
+ | ecco la mia versione: | ||
+ | <syntaxhighlight lang="Python"> | ||
+ | import os, hashlib | ||
+ | |||
+ | def fileCurrDir():#restituisce una lista res di file presenti nella directory | ||
+ | fcd = os.listdir('.') | ||
+ | res = [] | ||
+ | for ott in fcd: | ||
+ | if os.path.isfile('{0}'.format(ott)):res.append(ott) | ||
+ | else:continue | ||
+ | return res | ||
+ | |||
+ | def dictsize(fl=fileCurrDir()):#restituisce un dizionario con key filesize e value lista di filenames aventi size di filesize | ||
+ | res = {} | ||
+ | for f in fl: | ||
+ | if os.path.getsize('{0}'.format(f)) in list(res.keys()):res[os.path.getsize('{0}'.format(f))].append(f);continue | ||
+ | else:pass | ||
+ | res[os.path.getsize('{0}'.format(f))] = list() | ||
+ | res[os.path.getsize('{0}'.format(f))].append(f) | ||
+ | return res | ||
+ | |||
+ | def dictremsa(a=dictsize()):#data un dizionario key::list rimuove tutti gli item la cui len di lista sia unitaria | ||
+ | tmp = list(a.keys()) | ||
+ | for tmpkey in tmp: | ||
+ | if len(a[tmpkey]) < 2: a.pop(tmpkey) | ||
+ | else:continue | ||
+ | return a | ||
+ | |||
+ | def hashcontrolinsl(l1): #data una lista di nomi di file compara l hash di tutte le possibili coppie dentro l1 | ||
+ | while l1 != []: | ||
+ | toTest = l1.pop() | ||
+ | del res[:] | ||
+ | res.append(toTest) | ||
+ | for tmp in l1: | ||
+ | #res.append(list[toTest,tmp]) | ||
+ | #return res | ||
+ | hasher = hashlib.md5() | ||
+ | hasher2 = hashlib.md5() | ||
+ | f = open('{0}'.format(toTest), 'rb') | ||
+ | toHash = f.read() | ||
+ | hasher.update(toHash) | ||
+ | toTesthash = hasher.hexdigest() | ||
+ | f.close() | ||
+ | f = open('{0}'.format(tmp), 'rb') | ||
+ | toHash2 = f.read() | ||
+ | hasher2.update(toHash2) | ||
+ | tmphash = hasher2.hexdigest() | ||
+ | if tmphash==toTesthash: #print('{0} e {1} sono uguali\n'.format(toTest,tmp)) | ||
+ | res.append(tmp) | ||
+ | else:continue | ||
+ | if len(res)>1: | ||
+ | print(res);res.pop(0) | ||
+ | for j in res: | ||
+ | l1.pop(l1.index(j)) | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | def hashcontroltoMajorTom(a=dictremsa()):#fa in modo che vengano "hashate" solo delle liste di file che abbiano passato il "stessadimenzione" test | ||
+ | hasher = hashlib.md5() | ||
+ | try: | ||
+ | obviouslyequal = a.pop(0) | ||
+ | print("i seguenti file hanno lo stesso contenuto... NULLA!!!!!:\n") | ||
+ | for oe in obviouslyequal: | ||
+ | print("{0}".format(oe)) | ||
+ | except KeyError:pass | ||
+ | values = list(a.values()) | ||
+ | print("\ni seguenti file contengono qualcosa ma sono uguali:\n") | ||
+ | for namelist in values: | ||
+ | hashcontrolinsl(namelist) | ||
+ | |||
+ | |||
+ | hashcontroltoMajorTom() | ||
+ | </syntaxhighlight> | ||
+ | -fede | ||
+ | |||
+ | ===Bash=== | ||
+ | Qualche idea per Bash...<br/> | ||
+ | Si potrebbero usare:<br/> | ||
+ | Per la dimensione in byte dei <file>: | ||
+ | fileSize=$(stat --format=%s <file>) | ||
+ | Per avere l'output del solo hash md5 (senza l'ausilio di altri comandi): | ||
+ | fileHashMd5=$(md5sum <file> | while read fileHash fileName; do echo $fileHash; done) | ||
+ | |||
+ | <syntaxhighlight lang="Bash"> | ||
+ | #Fede&Alessio# | ||
+ | for file in *; do | ||
+ | if [[ -f "$file" ]] ; then | ||
+ | filesize=$(stat -c%s "$file") | ||
+ | for file2 in *; do | ||
+ | if [[ -f "$file2" ]] ; then | ||
+ | if [[ "$file" = "$file2" ]]; then | ||
+ | continue | ||
+ | fi | ||
+ | filesize2=$(stat -c%s "$file2") | ||
+ | if [[ $filesize -eq $filesize2 ]]; then | ||
+ | diff "$file" "$file2" && echo ""$file" == "$file2"" ### | ||
+ | fi | ||
+ | fi | ||
+ | done | ||
+ | fi | ||
+ | done | ||
+ | #Purtroppo non siamo riusciti a finire e abbiamo optato per una soluzione poco efficiente con un diff, poi continueremo per rendarlà un po migliore | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===Soluzione di Krusty=== | ||
+ | <source lang ="python"> | ||
+ | import os, sys | ||
+ | from stat import * | ||
+ | |||
+ | dic = {} | ||
+ | dir = os.getcwd() | ||
+ | for f in os.listdir(dir): | ||
+ | path = os.path.join(dir,f) | ||
+ | s = os.stat(path) | ||
+ | l = os.path.getsize(path) | ||
+ | if S_ISREG(s.st_mode): | ||
+ | if(l not in dic): | ||
+ | #aggiungo il percorso del file nel dizionario se non presente | ||
+ | f_list = [path] | ||
+ | dic[l] = f_list | ||
+ | else: | ||
+ | f_list = dic[l] #prelevo la lista di tutti i file lunghi l | ||
+ | f1 = open(path,"r") | ||
+ | text = f1.read() | ||
+ | f1.close() | ||
+ | for fl in f_list: | ||
+ | with open(fl,"r") as f2: | ||
+ | if(text == f2.read()): | ||
+ | print(f,'e',os.path.basename(fl),"hanno lo stesso contenuto") | ||
+ | f_list.append(path) | ||
+ | </source> |
Latest revision as of 08:22, 10 May 2017
Esercizio 1
Soluzione di Tommaso Ognibene
/*
Prova Pratica di Laboratorio di Sistemi Operativi
20 giugno 2013
Esercizio 1
URL: http://www.cs.unibo.it/~renzo/so/pratiche/2013.06.21.pdf
@author: Tommaso Ognibene
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
/* Comparison function for iNode
* Input: 2 dirent pointers
* Output:
* 1, if iNode[a] > iNode[b]
* 0, if iNode[a] == iNode[b]
* -1, else */
int iNodeComparison(const struct dirent **a, const struct dirent **b)
{
long iNodeA = (long)(*a)->d_ino;
long iNodeB = (long)(*b)->d_ino;
return (iNodeA > iNodeB) - (iNodeA < iNodeB);
}
/* Scan a directory ->
* Order the entries by iNode number ->
* Print name and iNode of each file. */
void scanDirectory(char *dir)
{
int result, iterator;
struct dirent **files;
result = scandir(dir, &files, NULL, iNodeComparison);
// Check if any errors occurred
if (result < 0)
{
perror("scandir()");
exit(EXIT_FAILURE);
}
// Loop through directory entries
for(iterator = 0; iterator < result; iterator++)
{
printf("%s/%s %li\n", dir, files[iterator]->d_name, (long)files[iterator]->d_ino);
// Garbage collection
free(files[iterator]);
}
free(files);
}
// Entry point
int main(int argc, char *argv[])
{
char cwd[1024];
// if (number of parameters
switch(argc)
{
// == 0) => Use the current directory
case 1:
if (!getcwd(cwd, sizeof(cwd)))
{
perror("getcwd()");
exit(EXIT_FAILURE);
}
scanDirectory(cwd);
exit(EXIT_SUCCESS);
// == 1) => Use the given directory
case 2:
scanDirectory(argv[1]);
exit(EXIT_SUCCESS);
// > 1) => Wrong input
default:
printf("The function requires 0 or 1 parameters.\n");
exit(EXIT_FAILURE);
}
}
Soluzione di Giulia N.
La mia versione:
/*Scrivere un programma che stampi il numero di inode di ogni file presente in una direcotory passata come argomento (o della
direcotry corrente se il programma viene chiamato senza parametri) e stampi l'elenco in ordine crescente di numero di i-node.
Es:
$ lsino demo
demo/. 1972484
demo/.. 1971834
demo/1.c 1972528
demo/a.out 1972485
demo/l1 1972486
demo/l2 1972486
demo/l3 1972486
demo/link.c 1972528*/
#define _SVID_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
int main(int argc, char *argv[]){
struct stat sb;
char cwd[1024];
struct dirent **namelist;
int n; /*valore di ritorno di scandir*/
int i=0;
if(argc>1){ /*se la directory e' stata data in input*/
strcpy(cwd,argv[1]);
}
else{ /*se la directory non viene data in input*/
getcwd(cwd, sizeof(cwd));
}
/*ora dentro cwd c'è la cartella interessata*/
n = scandir(cwd, &namelist, NULL, alphasort);
if(n<0)
perror("scandir");
else {
while (i<n) {
printf("%s/%s %ld\n", cwd,namelist[i]->d_name,(long)namelist[i]->d_ino);
free(namelist[i]);
i++;
}
free(namelist);
}
}
Non mi è chiara una cosa: nel testo specifica "stampi l'elenco in ordine crescente di numero di i-node", tuttavia nell'esempio sono ordinati grazie a quella che penso sia l'alphasort e quindi è la soluzione che ho sviluppato io. Giulia N.
Soluzione di D.Boldrin
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
typedef struct listnode { //struttura dati per contenere tutti gli inode dei file di una directory
struct listnode *next;
int inode;
}listnode;
int main(int argc, char* argv[]){
struct stat fileStat;
int contanode=0;
char *filename=argv[1];
struct stat tp;
DIR *path;
struct dirent *dir_object;
path = opendir(argv[1]);
listnode *root;
root = (listnode*)calloc(1, sizeof(listnode));
listnode *tmp=root;
dir_object = readdir(path); //comincia la scansione della cartella
while(dir_object != NULL){
stat(dir_object->d_name, &tp);
if (S_ISREG(tp.st_mode)){ //l'oggetto dir_object é un file,quindi lo salvo nella struttura
contanode++;
stat(dir_object->d_name, &fileStat);
tmp->inode=(fileStat.st_ino);
tmp->next=(listnode*)calloc(1, sizeof(listnode));
tmp=tmp->next;
}
dir_object = readdir(path);
}
printf("%d\n", contanode);
ordinaLista(root);
stampaLista(root);
}
void ordinaLista(listnode *pnt){
listnode *tmp=pnt;
int temp;
while(tmp->next!=NULL){
while(pnt->next!=NULL){
if(pnt->inode<tmp->inode){
temp=pnt->inode;
pnt->inode=tmp->inode;
tmp->inode=temp;
}
else{
pnt=pnt->next;
}
}
tmp=tmp->next;
pnt=tmp;
}
}
void stampaLista(listnode *pnt){
while(pnt->next!=NULL){
printf("%d\n",pnt->inode);
pnt=pnt->next;
}
}
Problema: Se come parametro gli passo l'indirizzo di una directory diverso da quella in cui si trova il file.c, non funziona, o meglio esegue, termina ma non trova alcun file all'interno della directory (anche se sono sicuro che i file ci sono).
Soluzione di blissett
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX 1000
/* struttura che salvera nome e i_node di ogni file presente nella directory */
typedef struct i_node {
int num;
char *nome;
}i_node;
static int confronto (i_node* elem1, i_node* elem2)
{
return (elem1->num - elem2->num);
}
int main (int argc, char *argv[])
{
int x=0;
int y=0;
DIR *root;
char *buf=malloc (100*(sizeof(char)));
struct dirent *d;
i_node A[MAX];
if (argv[1]==NULL)
{
getcwd(buf, MAX); /* prendo directory corrente e la salvo in buf */
if ((root = opendir (buf)) == NULL)
{
perror("opendir");
return -1;
}
}
else
{
buf =argv[1];
if ((root = opendir (buf)) == NULL)
{
perror("opendir");
return -1;
}
chdir(buf); /*cambio directory corrente con quella passato a linea di comando*/
}
/* SE VOGLIO STAMPARE SOLO I FILE REGOLARI
while ((d=readdir (root))!=NULL)
{
stat(d->d_name,&f);
if (S_ISREG(f.st_mode))
{
A[x].nome = d->d_name;
A[x].nodo = d->d_ino;
x++;
}
}
*/
/* scorro tutta la directory */
while ((d=readdir (root))!=NULL)
{
A[x].nome = d->d_name;
A[x].num = d->d_ino;
x++;
}
qsort(A, x--, sizeof(i_node), confronto); /* riodina seguendo la funzione "confronto" */
while (y<=x)
{
printf ("\n/%s ------ %d \n", A[y].nome, A[y].num);
y++;
}
}
--Blissett (talk) 09:36, 18 March 2015 (CET)
Esercizio 2
Soluzione di Alessandro C.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#define PATH_SIZE 1024
int iNoSort(const struct dirent** dir1, const struct dirent** dir2){
int a = (*dir1)->d_ino;
int b = (*dir2)->d_ino;
if (a<b) return -1;
else if (a>b) return 1;
else return 0;
}
int main(int argc, char** argv){
struct dirent** namelist;
int n, i, j;
int link = 0;
char path[PATH_SIZE];
if (argc == 1) {strcpy(path, "./");}
else if (argc == 2) {strcpy(path, argv[1]);}
n = scandir(path, &namelist, NULL, iNoSort);
if (n == -1) {perror("scandir"); exit(1);}
for (i=0; i<n; i++){
//printf("%s%s %d\n", path, namelist[i]->d_name, (int) namelist[i]->d_ino);
if (namelist[i]->d_ino == 0) continue;
for(j = i+1; j<n; j++){
if (namelist[j]->d_ino == namelist[i]->d_ino){
if (link == 0) {printf("%s ", namelist[i]->d_name); link++;}
printf("%s ",namelist[j]->d_name);
namelist[j]->d_ino = 0;
}
}
if(link > 0) printf("\n");
link = 0;
}
return 1;
}
Alessandro C.
Esercizio 3
Soluzione di Tommaso Ognibene
[Python 3]
'''
Prova Pratica di Laboratorio di Sistemi Operativi
20 giugno 2013
Esercizio 3
URL: http://www.cs.unibo.it/~renzo/so/pratiche/2013.06.21.pdf
@author: Tommaso Ognibene
'''
import os, sys, hashlib
def Main(argv):
# Check number of arguments
if len(argv) != 1:
print("The function does not require arguments to be passed in.")
return
# Build a dictionary with key-value pair {file size - [file name]}
sameSize = { }
PopulateSameSize(sameSize)
# Build a dictionary with key-value pair {MD5 hash - [file name]}
sameContent = { }
for filePaths in sorted(sameSize.values(), key = len, reverse = True):
# No files with same size => No files with same content
if len(filePaths) < 2: break
PopulateSameContent(filePaths, sameContent)
# Print results
PrintResults(sameContent)
print("Done!")
# Populate a dictionary with key-value pair {file size - [file name]}
def PopulateSameSize(sameSize):
for dirPath, _, fileNames in os.walk(os.getcwd()):
for fileName in fileNames:
filePath = os.path.join(dirPath, fileName)
fileSize = os.path.getsize(filePath)
sameSize[fileSize] = sameSize.get(fileSize, []) + [filePath]
# Populate a dictionary with key-value pair {MD5 hash - [file name]}
def PopulateSameContent(filePaths, sameContent):
for filePath in filePaths:
md5 = GetMd5Hash(filePath)
fileRelPath = os.path.relpath(filePath, os.getcwd())
sameContent[md5] = sameContent.get(md5, []) + [fileRelPath]
# Get the MD5 hash without loading the whole file to memory
# Break the file in chunks whose size is a multiple of 128
# This takes advantage of the fact that MD5 has 128-byte digest blocks
def GetMd5Hash(filePath, blockSize = 2 ** 20):
digest = hashlib.md5()
with open(filePath, "rb") as file:
for chunk in iter(lambda: file.read(blockSize), b''):
digest.update(chunk)
return digest.hexdigest()
# Printout the lists of files having same content
def PrintResults(sameContent):
print("Lists of files having same content:")
for files in sorted(sameContent.values(), key = len, reverse = True):
if len(files) < 2: break
print("[{0}]".format(", ".join(file for file in files)))
if __name__ == "__main__":
sys.exit(Main(sys.argv))
Soluzione di Fede
ecco la mia versione:
import os, hashlib
def fileCurrDir():#restituisce una lista res di file presenti nella directory
fcd = os.listdir('.')
res = []
for ott in fcd:
if os.path.isfile('{0}'.format(ott)):res.append(ott)
else:continue
return res
def dictsize(fl=fileCurrDir()):#restituisce un dizionario con key filesize e value lista di filenames aventi size di filesize
res = {}
for f in fl:
if os.path.getsize('{0}'.format(f)) in list(res.keys()):res[os.path.getsize('{0}'.format(f))].append(f);continue
else:pass
res[os.path.getsize('{0}'.format(f))] = list()
res[os.path.getsize('{0}'.format(f))].append(f)
return res
def dictremsa(a=dictsize()):#data un dizionario key::list rimuove tutti gli item la cui len di lista sia unitaria
tmp = list(a.keys())
for tmpkey in tmp:
if len(a[tmpkey]) < 2: a.pop(tmpkey)
else:continue
return a
def hashcontrolinsl(l1): #data una lista di nomi di file compara l hash di tutte le possibili coppie dentro l1
while l1 != []:
toTest = l1.pop()
del res[:]
res.append(toTest)
for tmp in l1:
#res.append(list[toTest,tmp])
#return res
hasher = hashlib.md5()
hasher2 = hashlib.md5()
f = open('{0}'.format(toTest), 'rb')
toHash = f.read()
hasher.update(toHash)
toTesthash = hasher.hexdigest()
f.close()
f = open('{0}'.format(tmp), 'rb')
toHash2 = f.read()
hasher2.update(toHash2)
tmphash = hasher2.hexdigest()
if tmphash==toTesthash: #print('{0} e {1} sono uguali\n'.format(toTest,tmp))
res.append(tmp)
else:continue
if len(res)>1:
print(res);res.pop(0)
for j in res:
l1.pop(l1.index(j))
def hashcontroltoMajorTom(a=dictremsa()):#fa in modo che vengano "hashate" solo delle liste di file che abbiano passato il "stessadimenzione" test
hasher = hashlib.md5()
try:
obviouslyequal = a.pop(0)
print("i seguenti file hanno lo stesso contenuto... NULLA!!!!!:\n")
for oe in obviouslyequal:
print("{0}".format(oe))
except KeyError:pass
values = list(a.values())
print("\ni seguenti file contengono qualcosa ma sono uguali:\n")
for namelist in values:
hashcontrolinsl(namelist)
hashcontroltoMajorTom()
-fede
Bash
Qualche idea per Bash...
Si potrebbero usare:
Per la dimensione in byte dei <file>:
fileSize=$(stat --format=%s <file>)
Per avere l'output del solo hash md5 (senza l'ausilio di altri comandi):
fileHashMd5=$(md5sum <file> | while read fileHash fileName; do echo $fileHash; done)
#Fede&Alessio#
for file in *; do
if [[ -f "$file" ]] ; then
filesize=$(stat -c%s "$file")
for file2 in *; do
if [[ -f "$file2" ]] ; then
if [[ "$file" = "$file2" ]]; then
continue
fi
filesize2=$(stat -c%s "$file2")
if [[ $filesize -eq $filesize2 ]]; then
diff "$file" "$file2" && echo ""$file" == "$file2"" ###
fi
fi
done
fi
done
#Purtroppo non siamo riusciti a finire e abbiamo optato per una soluzione poco efficiente con un diff, poi continueremo per rendarlà un po migliore
Soluzione di Krusty
import os, sys
from stat import *
dic = {}
dir = os.getcwd()
for f in os.listdir(dir):
path = os.path.join(dir,f)
s = os.stat(path)
l = os.path.getsize(path)
if S_ISREG(s.st_mode):
if(l not in dic):
#aggiungo il percorso del file nel dizionario se non presente
f_list = [path]
dic[l] = f_list
else:
f_list = dic[l] #prelevo la lista di tutti i file lunghi l
f1 = open(path,"r")
text = f1.read()
f1.close()
for fl in f_list:
with open(fl,"r") as f2:
if(text == f2.read()):
print(f,'e',os.path.basename(fl),"hanno lo stesso contenuto")
f_list.append(path)