#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <fcntl.h>
#define BUF  4096

#define MSG   "\nVerwendung : backup -[OPTION] [DATEIENDUNG] [NEUESVERZEICHNIS]\n"\
  "\nOptionen -b = Alle Dateien mit [DATEIENDUNG] als Backup\n"\
  "              in [NEUESVERZEICHNIS] kopieren\n"\
  "         -d = Alle Dateien mit [DATEIENDUNG] als Backup\n"\
  "              in [NEUESVERZEICHNIS] kopieren und diese\n"\
  "              Dateien im aktuellen Verzeichnis löschen\n"\
  "         -dw= Wie -d nur ohne Schreibrechte auf alle Dateien\n"\
  "         -dr= Wie -d nur ohne Schreib.-und-Leserechte auf Dateien\n"\
  "         -bw= Wie -d nur ohne Schreibrechte auf alle Dateien\n"\
  "              im neuen Verzeichnis.\n"\
  "         -br= Wie -d nur ohne Schreib.-und-Leserechte auf Dateien\n"\
  "              im neuen Verzeichnis.\n\n"\
  "[DATEIENDUNG] Schreibweise : txt,c,o,jpg, (mit Komma trennen und beenden)\n\n"

/*Flags für die Optionen von -1 bis 5 */
enum{NO_OPTION=-1,BACKUP,DELETE,DELETE_0444,DELETE_0000,BACKUP_0444,BACKUP_0000};
static int option;
char *dateiendung[10];  /*Auf 10 Dateiarten minimiert*/
char working_D[255];    /*Working Directory*/
char new_Directory[255]; /*Verzeichnis wo das Backup abgelegt wird*/

/*Funktionsprototypen*/
void error_exit(char *,...);
int get_option(char *);
void read_Directory(char *);
void copy_from_to(char *);


/*Fehlerausgabe mit exit*/
void error_exit(char *s,...)
{
 fprintf(stderr, "%s\n",s);
 exit(0);
}

/*2.Argument Optionen auswerten*/
int get_option(char *opt)
{
 if(strcmp(opt,"-b") == 0)
  return BACKUP;
 else if(strcmp(opt,"-d")==0)
  return DELETE;
 else if(strcmp(opt,"-dw") == 0)
  return DELETE_0444;
 else if(strcmp(opt,"-dr") == 0)
  return DELETE_0000;
 else if(strcmp(opt,"-bw") == 0)
  return BACKUP_0444;
 else if(strcmp(opt,"-br") == 0)
  return BACKUP_0000;
 else
  return NO_OPTION;
}


/*Verzeichnis lesen*/
void read_Directory(char *d)
{
 DIR *dir;
 struct dirent *dirzeiger;
 char *p,*p2;
 int i,j;
 char backup[255];

 if( (dir=opendir(d)) == NULL)
   error_exit("Konnte Verzeichnis %s nicht öffnen\n",d);
 while( (dirzeiger=readdir(dir)) != NULL)
  {
   i=0;j=0;
   while(dateiendung[i] != NULL)
    {
   /*Wir brauchen nur die Dateien mit den richtigen Endungen*/
   /*Zeiger auf Punkt, falls vorhanden*/
     if( (p=strchr((*dirzeiger).d_name,'.')) != NULL)
       /*Eine Position weiter und mit Liste dateiendung überprüfen*/
       if(strcmp((++p),dateiendung[i]) == 0){
         p2=(*dirzeiger).d_name;
         strncpy(backup,p2,strlen(p2)+1);
         /*Als Kontrolle*/
         /*printf("%s\n",backup);*/
         copy_from_to(backup);
         j++;
         break;
         }
      i++;
    }
  }
 closedir(dir);
}

void copy_from_to(char *b)
{
 //FILE *r,*w;
 int r,w;
 char dir1[255], dir2[255];
 int i,n;
 char puffer[BUF];
 int permission;

 strcpy(dir1,working_D); strcat(dir1,"/"); strcat(dir1,b);
 strcpy(dir2, new_Directory); strcat(dir2,"/"); strcat(dir2,b);
 printf("from : %s to : %s\n",dir1,dir2);

 /*Datei zum lesen öffnen*/
 //r=fopen(dir1,"r");
 r=open(dir1,O_RDONLY);
 /*Datei zum Schreiben im neuen Verzeichnis öffnen*/
 //w=fopen(dir2,"w");
 w=open(dir2,O_WRONLY|O_CREAT|O_TRUNC);
 if(r==-1)
  fprintf(stderr,"Konnte Datei %s nicht öffnen(read)\n",dir1);
 if(w==-1)
  fprintf(stderr,"Konnte Datei %s nicht öffnen(write)\n",dir2);
 /*Kopieren ins neue Verzeichnis*/
 while( (n=read(r, &puffer, BUF)) > 0)
   write(w,&puffer,n);

 /*War ein Flag zum löschen gesetzt?*/
 if(option==DELETE || option==DELETE_0444 || option==DELETE_0000)
  if(remove(dir1) == -1) /*dann weg damit*/
    fprintf(stderr, "Konnte %s nicht löschen!\n",dir1);

 /*Haben wir als Option ein r oder w für Zugriffrechte verwendet?*/
 if(option==BACKUP_0000 || option==DELETE_0000)
   permission=0000;
 else if(option==BACKUP_0444 || option==DELETE_0444)
   permission=0444;
 else
   permission=0750;
  if(fchmod(w,permission) == -1)
   fprintf(stderr,"Konnte Zugriffrechte für %s nicht ändern\n",dir2);

 close(r);close(w);
}



int main(int argc, char **argv)
{
 int i;
 char *p;
 char arg2[255];

 if(argc < 4)
   error_exit(MSG);

 /*Optionen auswerten*/
 option=get_option(argv[1]);
 if(option == NO_OPTION)
   error_exit(MSG);

 /*Dateiendungen auswerten*/
 strncpy(arg2, argv[2], strlen(argv[2]));
 p=strtok(arg2,",");
 for(i=0; i<10 && p!=NULL; i++)
  {
   if ((*(dateiendung+i)=malloc(strlen(p))) == NULL)
     error_exit("Konnte keinen Speicher reservieren");
   strncpy(*(dateiendung+i),p, strlen(p));
   p=strtok(NULL,",");
  }
 printf("Nach folgenden Dateien wird nun gesucht : ");
 for(i=0; *(dateiendung+i) != NULL; i++)
   printf("*.%s ; ",*(dateiendung+i));
 printf("\n");
 /*Ende Dateiendungen auswerten*/

 /*aktuelles Verzeichnis Öffnen und Lesen */
 if((getcwd(working_D, sizeof(working_D))) == NULL)
   error_exit("Konnte Working Directory nicht ermitteln");
 else
   printf("Im folgenden Verzeichnis wird gesucht   : %s\n",working_D);

 strncpy(new_Directory, argv[3], strlen(argv[3]));
 printf("Backup kommt in folgendes Verzeichnis   : %s\n",new_Directory);

 /*Verzeichnis für Backup anlegen*/
 if(mkdir(new_Directory,0755) == -1)
  error_exit("Konnte neuen Verzeichnis nicht erstellen");

 read_Directory(working_D); /*Verzeichnis lesen und Liste erstellen*/

 return 0;
}