Esercizio 1, prova pratica 17.06.2014

From Sistemi Operativi
Jump to navigation Jump to search
Occorre scrivere due programmi: mytar myuntar.
Mytar prende come parametro il nome di una directory e il nome di un file:
mytar ddd ddd.mytar
mytar crea il file indicato come secondo parametro e registra in esso tutti i file regolari presenti nella directory (ddd
nell'esempio). Ogni file e' registrato nel secondo il seguente formato:
nome del file (stringa ASCII terminata da un byte 0)
lunghezza del file (stringa ASCII terminata da 0, la lunghezza e' registrata come stringa in rappresentazione in base 10
per non avere problemi di endianess e di ampiezza dei campi)
contenuto del file (un numero di byte corrispondente alla lunghezza indicata sopra).
Myuntar fa l'operazione inversa:
myuntar ddd.mytar newddd
crea la directory indicata come secondo parametro e, in essa, tutti i file registrati in ddd.mytar.
Per provare i due programmi, al termine dell'esecuzione di due comandi simili a quelli degli esempi mostrati qui sopra per
mytar e myuntar, tutti i file regolari presenti in ddd devono esistere in newddd e devono avere tutti lo stesso contenuto.
Se create una directory ddd contenente solo file regolare l'output di “diff -R ddd newddd” deve essere vuoto.

Soluzione di Dado

mytar e myuntar entrambi funzionanti


mytar.c

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

#define MAX 20
#define MAXI 1024

/*codice copiato da internet che ipotizzo funzioni :) */

 void reverse(char s[])
 {
     int i, j;
     char c;
 
     for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
         c = s[i];
         s[i] = s[j];
         s[j] = c;
     }
 }

void itoa(int n, char s[])
 {
     int i, sign;
 
     if ((sign = n) < 0)  /* record sign */
         n = -n;          /* make n positive */
     i = 0;
     do {       /* generate digits in reverse order */
         s[i++] = n % 10 + '0';   /* get next digit */
     } while ((n /= 10) > 0);     /* delete it */
     if (sign < 0)
         s[i++] = '-';
     s[i] = '\0';
     reverse(s);
 }


/*mytar*/
int main(int argc, char * argv[]){
	if(argc!=3){
		fprintf(stderr, "Wrong arguments number\n");
		return -1;
	}
	else{
		FILE *dest;
		FILE *temp;
		DIR *dir;
		char length[MAX];
		char *buf_read;
		char zero='\0';
		size_t n_readed;
		struct stat buf;
		struct dirent *entry;
		if((dir=opendir(argv[1]))==NULL){
			fprintf(stderr, "Error opendir\n");
			exit(-1);
		}
		if((dest=fopen(argv[2],"w"))==NULL){
			fprintf(stderr, "Error fopen\n");
			exit(-1);
		}
		while((entry=readdir(dir))!=NULL){
			buf_read=NULL;
			chdir(argv[1]);
			if(entry->d_type==DT_REG){
				if(stat(entry->d_name,&buf)==-1){
					fprintf(stderr, "Error stat\n");
					exit(-1);
				}
				if((temp=fopen(entry->d_name,"r"))==NULL){
					fprintf(stderr, "Error fopen_temp\n");
					exit(-1);
				}
				write(fileno(dest),entry->d_name,strlen(entry->d_name)+1);
				itoa(buf.st_size-1,length);
				write(fileno(dest),length,strlen(length)+1);
				/*scrivere dati*/
				while(getdelim(&buf_read,&n_readed,EOF,temp)>0){
					write(fileno(dest),buf_read,strlen(buf_read)-1);
				}
				free(buf_read);
			}
		}
		printf("File mytar creato con successo!\n");
		return 0;
	}
}


myuntar.c

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


int main(int argc, char * argv[]){
	if(argc!=3){
		fprintf(stderr, "Wrong arguments number\n");
		exit(-1);
	}else{
		FILE *mytar;
		FILE *tmp;
		char nome[256];
		int dim, i;
		char readed[2],length[20];
		nome[0]=length[0]=0;
		readed[1]=0;
		if(mkdir(argv[2],(mode_t)0777)==-1){
			fprintf(stderr, "Error mkdir\n");
			exit(-1);
		}
		if((mytar=fopen(argv[1],"r"))==NULL){
			fprintf(stderr, "Error fopen\n");
			exit(-1);
		}
		if(chdir(argv[2])==-1){
			fprintf(stderr, "Errore chdir\n");
			exit(-1);
		}
		while((fread(&readed,1,1,mytar))){
			strcat(nome,readed);
			while((fread(&readed,1,1,mytar))){
				if(readed[0]=='\0') break;
				strcat(nome,readed);
			}
			printf("Nome trovato: %s\n",nome);
			if((tmp=fopen(nome,"w"))==NULL){
				fprintf(stderr, "Error fopen files\n");
				exit(-1);
			}
			while((fread(&readed,1,1,mytar))){
				if(readed[0]=='\0') break;
				strcat(length,readed);
			}
			dim=atoi(length);
			printf("Lunghezza trovata: %s\n",length);
			for(i=0; i<dim; i++){
				fread(&readed,1,1,mytar);
				write(fileno(tmp),&readed,1);
			}
		fclose(tmp);
		nome[0]=0;
		length[0]=0;
		}
	fclose(mytar);
	printf("File myuntar scompattato correttamente, credo\n");
	return 0;
	}
}


Soluzione di MV

Per ora ho fatto solo la prima parte, cioè mytar.
L'unico problema che non riesco a capire è che entra in un loop infinito (scrivendo all'infinito sul file che crea!) se viene usato nella cartella dell'eseguibile stesso...
/*-------------------------------------MYTAR.C--------------------------------------------*/

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

#define BUF_DIM 512

/* scrive nome, dimensione e contenuto del file indicato da src nel file dest (già aperto in scrittura) */
int filecpy(const char *src, const int dest, off_t size);

/* ---------------------------------- MAIN ------------------------------- */
int main(int argc, char* argv[])
{	
	DIR *ddd;
	int f;
	struct dirent *entry;
	struct stat dest_st;
	int e,i,len;
	char buf[BUF_DIM];
	
	if(argc != 3)
	{
		printf("Error: needed 2 parameters\n");
		return 1;
	}
	
	umask(0001);
	/* Creo il file passato come secondo parametro */
	if((f = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
	{
		printf("Error in open(): %s (%i)\n",strerror(errno),errno);
		return errno;
	}
	
	/* Apro la directory passata come primo parametro, se c'è */
	if((ddd = opendir(argv[1])) == NULL)
	{
		printf("Error in opendir(%s): %s (%i)\n",argv[1],strerror(errno),errno);
		return errno;
	}
	/* mi sposto in quella directory */
	if(chdir(argv[1]) == -1)
	{
		printf("Error in chdir(%s): %s (%i)\n",argv[1],strerror(errno),errno);
		return errno;
	}
	
	e = errno;
	i = 0;	/* in i mantengo il numero totale di file copiati */
	/* leggo lo stat del file che ho creato */
	if(fstat(f, &dest_st) == -1)
	{
		printf("Error in stat(%s): %s (%i)\n",buf,strerror(errno),errno);
		return errno;
	}
	
	/* leggo le entry della directory finchè ce ne sono */
	while((entry = readdir(ddd)) != NULL)
	{
		struct stat st;
		
		strcpy(buf, entry->d_name);
		
		if(stat(buf, &st) == -1)
		{
			printf("Error in stat(%s): %s (%i)\n",buf,strerror(errno),errno);
			return errno;
		}
		else if(st.st_mode & S_IFREG)	/* è un file */
		{	
			/* verifico che il file in questione sia diverso da quello aperto in scrittura, per evitare che scriva su se stesso all'infinito */
			if((st.st_ino == dest_st.st_ino) && (st.st_rdev == dest_st.st_rdev))
				continue;
			
			if(filecpy(buf, f, st.st_size) == -1)
			{
				printf("Error in filecpy(%s, %i)\n",buf,f);
				return -1;
			}
			printf("%s inserito.\n", buf);
			i++;
		}
	}
	
	if(e != errno)	/* sono uscito dal ciclo a causa di un errore */
	{
		printf("Error in readdir(): %s (%i)\n",strerror(errno),errno);
		return errno;			
	}
	else	/* perchè ho visitato tutte le entrate della directory */
		printf("end of directory, %i entry found.\n", i);
	
	return 0;
}

int filecpy(const char *src, const int dest, off_t size)
{
	/* NB: dest è già aperto in scrittura */
	int s, len, tot;
	char buf[BUF_DIM];
	
	if((s = open(src,O_RDONLY,0)) == -1)	/* apro src in lettura */
		return -1;
	
	tot = write(dest, src, strlen(src)+1);	/* per prima cosa copio il titolo del file src */
							/* NB: faccio tot+1 per copiare anche lo 0 terminatore */
	sprintf(buf, "%i", (int)size);	/* poi copio la dimensione */
	tot += write(dest, buf, strlen(buf)+1);
	
	/* infine copio tutto il contenuto */
	while( (len = read(s,buf,BUF_DIM)) != 0)
	{
		if(len == -1)
		{
			printf("Error in read(): %s (%i)\n",strerror(errno),errno);
			return -1;
		}
		/*else printf("%i\n",len);*/
		tot += write(dest, buf, len);
	}
	
	return tot;	/* restituisce il numero totale di byte scritti */
}