/*----------------------------------------------------------------
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;
}