/*---------------------------------------------------------------- RED Remove Empty Directory Questo programma richiede in linea il nome di una directory in cui si abbia anche, ma soprattutto, il diritto di scrittura. Legge ricorsivamente le directory sottostanti eliminando quelle vuote. Se del caso, rimuove anche quella passata come parametro in linea. Benche` abbia eseguito vari controlli e posto la massima cura non posso escludere malfunzionamenti. Chiunque puo' usarlo, ma a pro- prio rischio e pericolo. Non sono assolutamente responsabile di danni e/o perdite di dati riconducibili alla sua esecuzione. Configurazione Il programma lavora silenziosamente. La variabile d'ambiente RED_VERBOSE se posta a yes oppure si oppure 1 attiva la modalita' verbose (vengono stampate le directory rimosse). In caso contra- rio oppure in sua mancanza la disattiva. Messaggistica Uso: red nome directory al programma va passata obbligatoriamente una directory directory xxxx errata|non esiste la directory passata in linea non esiste oppure non puo' es- sere acceduta errore apertura directory xxxx la directory in questione non puo' essere aperta per l'ispe- zione stat errata per xxxx impossibile determinare il tipo di file path (xxx/xxx) troppo lungo il nome della directory, compreso il path, e' superiore al massimo consentito xxxx non cancellata la directory in questione non puo' essere rimossa xxxx cancellata la directory e' stata rimossa (solo se la modalita' VERBOSE e' attivata) ----------------------------------------------------------------*/ #include <dirent.h> #include <linux/limits.h> #include <regex.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> int main (int argc, char **argv) { char dovesono [PATH_MAX+NAME_MAX], *p; int leggidir (char *, int, int), stampa; extern int match (char *, char *, regmatch_t *); regmatch_t pmatch; if (argc != 2) { fprintf (stderr, "Uso: %s nome directory\n", argv[0]); exit (EXIT_FAILURE); } memset (dovesono, (int) NULL, sizeof dovesono); getcwd (dovesono, sizeof dovesono); strcat (strcat (dovesono, "/"), argv[1]); if (chdir (dovesono) == -1) { fprintf (stderr, "directory %s errata|non esiste\n", argv[1]); exit (EXIT_FAILURE); } p = getenv ("RED_VERBOSE"); if (p == NULL) stampa = 0; else stampa = match (p, "[yY][eE][Ss]|[Ss][iI]|^1$", &pmatch); (void) leggidir (dovesono, sizeof dovesono, stampa); exit (EXIT_SUCCESS); } int leggidir (char *dir, int len, int stampa) { char *p; DIR *d; int n, nentry; struct dirent *ds; struct stat buffer; if ((d = opendir (dir)) == NULL) { fprintf (stderr, "errore apertura directory %s\n", dir); exit (EXIT_FAILURE); } nentry = 0; while ((ds = readdir (d))) { if (stat (ds->d_name, &buffer) == -1) { fprintf (stderr, "stat errata per %s\n", ds->d_name); exit (EXIT_FAILURE); } nentry++; if (S_ISDIR (buffer.st_mode)) if (strcmp (ds->d_name, ".") && strcmp (ds->d_name, "..")) { n = strlen (ds->d_name); if ((n+1+strlen(dir)) > len) { fprintf (stderr, "path (%s/%s) troppo lungo\n", dir, ds->d_name); exit (EXIT_FAILURE); } strcat (strcat (dir, "/"), ds->d_name); chdir (dir); nentry += leggidir (dir, len, stampa); for (p = strrchr (dir, '/'); n; n--) *p++ = (int) NULL; chdir (dir); } } closedir (d); if (nentry == 2) { if (rmdir (dir) == -1) { fprintf (stderr, "%s non cancellata\n", dir); exit (EXIT_FAILURE); } if (stampa) printf ("%s cancellata\n", dir); return -1; } else return 0; }