Difference between revisions of "ProvaPratica 2013.06.21"

From Sistemi Operativi
Jump to navigation Jump to search
m (Aggiunte soluzioni da altre pagine)
 
(23 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 files in sorted(sameSize.values(), key = len, reverse = True):
+
     for filePaths in sorted(sameSize.values(), key = len, reverse = True):
         if len(files) < 2:
+
        # No files with same size => No files with same content
            break
+
         if len(filePaths) < 2: break
         PopulateSameContent(files, sameContent)
+
         PopulateSameContent(filePaths, sameContent)
  
 
     # Print results
 
     # Print results
Line 38: Line 414:
 
# 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, dirNames, fileNames in os.walk(os.getcwd()):
+
     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 45: Line 421:
 
   
 
   
 
# Populate a dictionary with key-value pair {MD5 hash - [file name]}
 
# Populate a dictionary with key-value pair {MD5 hash - [file name]}
def PopulateSameContent(files, sameContent):
+
def PopulateSameContent(filePaths, sameContent):
     for filePath in files:
+
     for filePath in filePaths:
         md5 = Md5Checksum(filePath)
+
         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]
  
# Compute the MD5 hash of a file
+
# Get the MD5 hash without loading the whole file to memory
def Md5Checksum(filePath):
+
# Break the file in chunks whose size is a multiple of 128
     with open(filePath, 'rb') as file:
+
# This takes advantage of the fact that MD5 has 128-byte digest blocks
         m = hashlib.md5()
+
def GetMd5Hash(filePath, blockSize = 2 ** 20):
        while True:
+
    digest = hashlib.md5()
            data = file.read(8192)
+
     with open(filePath, "rb") as file:
            if not data:
+
         for chunk in iter(lambda: file.read(blockSize), b''):  
                break
+
             digest.update(chunk)
             m.update(data)
+
    return digest.hexdigest()
        return m.hexdigest()
 
  
 
# Printout the lists of files having same content
 
# Printout the lists of files having same content
 
def PrintResults(sameContent):
 
def PrintResults(sameContent):
     print('List of files having same content:')
+
     print("Lists of files having same content:")
     for list in sameContent.values():
+
     for files in sorted(sameContent.values(), key = len, reverse = True):
         if len(list) > 1:
+
         if len(files) < 2: break
            print("[{0}]".format(", ".join(str(i) for i in list)))
+
        print("[{0}]".format(", ".join(file for file in files)))
 
          
 
          
 
if __name__ == "__main__":
 
if __name__ == "__main__":
Line 73: Line 448:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
+
===Soluzione di Fede===
 
 
----
 
 
 
 
 
 
 
----
 
  
 
ecco la mia versione:
 
ecco la mia versione:
Line 109: Line 478:
 
return a
 
return a
  
def hashcontrolinsl(l1): #data una lista di nomi di file compara l hash di tutte le possibili coppie dentro la lista
+
def hashcontrolinsl(l1): #data una lista di nomi di file compara l hash di tutte le possibili coppie dentro l1
res = []
 
 
while l1 != []:
 
while l1 != []:
 
toTest = l1.pop()
 
toTest = l1.pop()
 +
del res[:]
 +
res.append(toTest)
 
for tmp in l1:
 
for tmp in l1:
 
#res.append(list[toTest,tmp])
 
#res.append(list[toTest,tmp])
Line 127: Line 497:
 
hasher2.update(toHash2)
 
hasher2.update(toHash2)
 
tmphash = hasher2.hexdigest()
 
tmphash = hasher2.hexdigest()
if tmphash==toTesthash: print('{0}   \t e   \t {1}  sono uguali\n'.format(toTest,tmp))
+
if tmphash==toTesthash: #print('{0} e {1}  sono uguali\n'.format(toTest,tmp))
 +
res.append(tmp)
 
else:continue
 
else:continue
 +
if len(res)>1:
 +
print(res);res.pop(0)
 +
for j in res:
 +
l1.pop(l1.index(j))
 +
 
 
  
Line 134: Line 510:
  
  
def hashcontroltoMajorTom(a=dictremsa()):#fa in modo che vengano "hashati" solo delle liste di file che abbiano passato il "stessadimenzione" test
+
def hashcontroltoMajorTom(a=dictremsa()):#fa in modo che vengano "hashate" solo delle liste di file che abbiano passato il "stessadimenzione" test
 
hasher = hashlib.md5()
 
hasher = hashlib.md5()
obviouslyequal = a.pop(0)
+
try:
print("i seguenti file hanno lo stesso contenuto... NULLA!!!!!:\n")
+
obviouslyequal = a.pop(0)
for oe in obviouslyequal:
+
print("i seguenti file hanno lo stesso contenuto... NULLA!!!!!:\n")
print("{0}".format(oe))
+
for oe in obviouslyequal:
 +
print("{0}".format(oe))
 +
except KeyError:pass
 
values = list(a.values())
 
values = list(a.values())
print("\nle seguenti coppie invece contengono qualcosa ma sono uguali:\n")
+
print("\ni seguenti file contengono qualcosa ma sono uguali:\n")
 
for namelist in values:
 
for namelist in values:
 
hashcontrolinsl(namelist)
 
hashcontrolinsl(namelist)
Line 149: Line 527:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
-fede
 
-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)