Skip to content

Instantly share code, notes, and snippets.

@sescobb27
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sescobb27/e0b608d2bf07db5c4bf6 to your computer and use it in GitHub Desktop.
Save sescobb27/e0b608d2bf07db5c4bf6 to your computer and use it in GitHub Desktop.
#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