Last active
August 29, 2015 14:02
-
-
Save sescobb27/e0b608d2bf07db5c4bf6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <dirent.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#define CREATE 1 | |
#define NOCREATE 0 | |
#define SUCCESS 0 | |
#define TRY_AGAIN 1 | |
void move( char*, char* ); | |
int assert_no_error( DIR*, char*, int ); | |
char * get_dir_name_from_path( char* ); | |
void append_to( char*, char* ); | |
void list_dir( char* ); | |
int main(int argc, char const *argv[]) | |
{ | |
// el primer parametro es el nombre del comando y se necesitan otros 2 mas | |
if (argc < 3) { | |
fprintf(stderr, "%s\n%s", "No hay suficientes parametros:", | |
"El correcto uso es move_dir ORIGIN_DIR DEST_DIR"); | |
exit(EXIT_FAILURE); | |
} | |
int i; | |
// last_dir es el directorio al que vamos a mover | |
char *last_dir = argv[ argc - 1 ]; | |
char *dir = NULL; | |
for ( i = 1; i < argc - 1; ++i ) { | |
dir = argv[i]; | |
list_dir( dir ); | |
move(dir, last_dir); | |
} | |
return 0; | |
} | |
// esta funcion se asegura que no haya un error a la hora de abrir un | |
// directorio, dependiendo del flag que se le pase por parametros | |
// (CREATE o NOCREATE) crea el directorio. Cuando lo crea retorna | |
// TRY_AGAIN para que se vuelva a ejecutar esta funcion | |
int assert_no_error(DIR *dir, char *dir_name, int flag) | |
{ | |
if (dir == NULL) { | |
switch( errno ) { | |
case EACCES: | |
fprintf(stderr, | |
"Reason:\n\t%s %s\n", | |
"Read Permission is denied for the directory", | |
dir_name); | |
break; | |
case ENOENT: | |
if ( flag == NOCREATE ) { | |
printf("No such file or directory: %s\n", dir_name); | |
break; | |
} | |
int status = mkdir(dir_name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); | |
if (status != 0) { | |
printf("Error attempting to create directory\n"); | |
break; | |
} else { | |
return TRY_AGAIN; | |
} | |
} | |
closedir(dir); | |
exit(EXIT_FAILURE); | |
} | |
return SUCCESS; | |
} | |
// esta funcion obtiene del path el directorio objetivo, ejemplo: | |
// path -> /home/user/prueba | |
// return -> prueba | |
// path -> /home/user/prueba/ | |
// return -> prueba | |
char * get_dir_name_from_path( char *path ) | |
{ | |
unsigned int len_path = strlen(path); | |
char *tmp = NULL, | |
*dir_name = NULL, | |
*p_char = NULL; | |
int pos; | |
// pregunta si el ultimo caracter del path tiene o no un / | |
// si lo tiene copia a tmp todo el path hasta ese / sin incluirlo, | |
// pregunta al string tmp la posicion del ultimo / que seria el anterior | |
// al nombre del directorio y copia apartir de ahi hasta el final | |
if (path[ len_path - 1 ] == '/') { | |
tmp = (char *) malloc( len_path - 1 ); | |
strncpy( tmp, path, len_path - 1); | |
--len_path; | |
} else { | |
tmp = (char *) malloc( len_path ); | |
strncpy( tmp, path, len_path ); | |
} | |
p_char = strrchr( tmp, '/' ); | |
pos = p_char - tmp + 1; | |
dir_name = (char *)malloc(len_path - pos); | |
int i = 0; | |
for (; pos < len_path ; ++pos, ++i) { | |
dir_name[i] = tmp[pos]; | |
} | |
strcat( dir_name, "\0"); | |
return dir_name; | |
} | |
// agrega al path el nombre del directorio que vamos a crear | |
// ejemplo: | |
// dst_path -> /home/user/ | |
// name -> prueba | |
// RESULT -> | |
// dst_path -> /home/user/prueba | |
void append_to( char *dst_path, char *name) | |
{ | |
int len_path = strlen(dst_path); | |
if (dst_path[ len_path - 1 ] == '/') { | |
strcat( dst_path, name ); | |
} else { | |
strcat(dst_path, "/"); | |
strcat(dst_path, name); | |
} | |
} | |
void list_dir(char *path) | |
{ | |
DIR *dir = opendir(path); | |
assert_no_error( dir, path, NOCREATE ); | |
struct dirent *dp = NULL; | |
struct stat statbuf; | |
char *inner_path_dir = NULL; | |
do { | |
if ( (dp = readdir(dir)) != NULL ){ | |
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { | |
continue; | |
} | |
inner_path_dir = (char *) malloc( strlen(path) ); | |
memcpy( inner_path_dir, path, strlen(path)); | |
append_to( inner_path_dir, dp->d_name ); | |
if (stat(inner_path_dir, &statbuf) == 0) { | |
if ( S_ISDIR(statbuf.st_mode ) ) { | |
list_dir(inner_path_dir); | |
} else { | |
fprintf(stdout, "Dir: %-50sFile: %s\n", path, dp->d_name); | |
} | |
} | |
} | |
} while (dp != NULL); | |
closedir(dir); | |
} | |
void move(char *src_dir, char *dst_dir) | |
{ | |
DIR *src_dir_DIR = NULL, | |
*dst_dir_DIR = NULL; | |
src_dir_DIR = opendir(src_dir); | |
assert_no_error( src_dir_DIR, src_dir, NOCREATE ); | |
dst_dir_DIR = opendir(dst_dir); | |
int status = assert_no_error( dst_dir_DIR, dst_dir, CREATE ); | |
if (status == TRY_AGAIN) { | |
dst_dir_DIR = opendir(dst_dir); | |
} | |
int success = rename(src_dir, dst_dir); | |
if (success == -1) { | |
switch(errno) { | |
case EACCES: | |
fprintf(stderr, | |
"Reason:\n\t%s\n", | |
"Write Permission is denied for the directory"); | |
closedir( src_dir_DIR ); | |
closedir( dst_dir_DIR ); | |
exit(EXIT_FAILURE); | |
case EINVAL: | |
// copia manual | |
fprintf(stderr, "%s\n", | |
"An attempt was made to make a directory a subdirectory of itself"); | |
closedir( src_dir_DIR ); | |
closedir( dst_dir_DIR ); | |
exit(EXIT_FAILURE); | |
case ENOENT: | |
fprintf(stderr, "%s\n", "No such file or directory"); | |
closedir( src_dir_DIR ); | |
closedir( dst_dir_DIR ); | |
exit(EXIT_FAILURE); | |
case ENOTEMPTY: | |
{ | |
char *dir_name = NULL; | |
dir_name = get_dir_name_from_path( src_dir ); | |
closedir( dst_dir_DIR ); | |
closedir( src_dir_DIR ); | |
char *tmp = (char *)malloc( strlen(dst_dir) ); | |
memcpy( tmp, dst_dir, strlen(dst_dir)); | |
append_to( tmp, dir_name ); | |
move(src_dir, tmp); | |
return; | |
} | |
} | |
} | |
closedir( src_dir_DIR ); | |
closedir( dst_dir_DIR ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment