I wrote a program that copies a directory from a source to a destination, similar to the cp
utility.
For this, I used the essential functions:
open(), write(), mkdir(), readdir().
This is the source code (ignore the main()
function, this is not the final form):
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int isDirectory(char*);
int copyFile(char*, char*);
int copyDirectory(char*, char*);
int main(int argc, char **argv) {
copyDirectory(*(argv + 1), *(argv + 2));
return 0;
}
int isDirectory(char *path) {
struct stat statbuf;
if (stat(path, &statbuf) == -1) {
return -1;
}
else {
return S_ISDIR(statbuf.st_mode);
}
}
int copyFile(char *source, char *destination) {
if((source == NULL) || (destination == NULL)) {
return -1;
}
struct stat statbuf;
int fdr, fdw, rv;
char buff[256];
stat(source, &statbuf);
if(!S_ISREG(statbuf.st_mode)) {
return 1;
}
fdr = open(source, O_RDONLY);
fdw = open(destination, O_CREAT|O_WRONLY, S_IREAD|S_IWRITE);
while((rv = read(fdr, &buff, 128))) {
write(fdw, &buff, rv);
}
return 0;
}
int copyDirectory(char *source, char *destination) {
if((source == NULL) || (destination == NULL)) {
return -1;
}
struct dirent *entry;
DIR *dr;
char sourcePatch[512], destinationPatch[512];
strcpy(sourcePatch, source);
strcpy(destinationPatch, destination);
strcat(destinationPatch, "/");
strcat(sourcePatch, "/");
if(!isDirectory(source)) {
return -1;
}
if(opendir(destination) == NULL) {
mkdir(destination, 0700);
}
dr = opendir(source);
while((entry = readdir(dr))) {
strcat(sourcePatch, entry->d_name);
strcat(destinationPatch, entry->d_name); //printf("%s\n", sourcePatch);
if(isDirectory(sourcePatch) && strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
copyDirectory(sourcePatch, destinationPatch);
}
else {
copyFile(sourcePatch, destinationPatch);
}
*sourcePatch = '\0'; *destinationPatch = '\0';
strcpy(sourcePatch, source);
strcpy(destinationPatch, destination);
strcat(destinationPatch, "/");
strcat(sourcePatch, "/");
}
return 0;
}
Is there a better way for doing this?
Comparing my program, to the GNU cp
program, I get this results:
[marius@arch labs]$ gcc -Wall cp.c -g -O3 -o cp
[marius@arch labs]$ time ./cp ~/Desktop/management ~/Desktop/testtest
real 0m0.139s
user 0m0.003s
sys 0m0.133s
[marius@arch labs]$ time cp -r ~/Desktop/management ~/Desktop/testtest2
real 0m0.018s
user 0m0.000s
sys 0m0.017s
And what about this code, can I make some improvements?