Copy files of directory into another using system calls on linux - c

Im trying to copy the files from a directory into another using system calls but i get a "violation of segment core" and I don't know why, the first argument is the origin directory, the second the destiny directory, the third is not used and the fourth is the bytes position where I start to copy every file of the first directory with this I mean for example if Pos = 4 and the file is helloo the copied file content would be o because I use lseek to move to pointer to the position 4 and start to copy from there, this is my code:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define BS 512
#define error(a) {perror(a); exit(1);};
int main(int argc, char *argv[]) //argv1 Dir1 argv2 Dir2 argv3 Fich argv4 Pos
{
DIR *dir1;
DIR *dir2;
struct dirent *lectura1;
struct dirent *lectura2;
struct stat st;
int datos1;
int datos2;
int size;
char path[256] = "";
char path2[256] = "";
char temp[256];
char buf[BS];
int j;
int i;
if(argc != 5)
{
error("Numero de argumentos incorrecto");
}
int Pos = atoi(argv[4]);
if(Pos < 0)
{
error("Pos must be 0 or greater")
}
if((dir1 = opendir(argv[1])) == NULL){error("Failed to open origin dir");}
if((dir2 = opendir(argv[2])) == NULL){error("Failed to open destiny dir");}
while((lectura1 = readdir(dir1)) != NULL)
{
sprintf(path, "%s/%s", argv[1], lectura1->d_name);
lectura2 = readdir(dir2);
sprintf(path2, "%s/%s", argv[2], lectura2->d_name);
if (strcmp(lectura1->d_name, "..") != 0 && strcmp(lectura1->d_name, ".") != 0)
{
if (stat(path, &st) == 0)
{
if (S_ISREG(st.st_mode)) //If is a regular file
{
if((datos1 = open(path, O_RDONLY, 00600)) == -1){error("Failed to open file");} //Opens the target file of Dir1 to copy inside Dir2
size = lseek(datos1,0,SEEK_END);
if (size > Pos) //Check if the size of the file is bigger than the position that indicates the point from which to start copying the file
{
lseek(datos1,Pos,SEEK_SET); //Moves the pointer to the start position of the file1
if((datos2 = open(path2, O_CREAT|O_WRONLY, 00200)) == -1){error("Error al abrir archivo copia");}
lseek(datos2,0,SEEK_SET);
j = BS;
i = 0;
int n = 0;
if ((size - i) < BS)
{
j = size - i;
}
while ((n = read(datos1, buf, BS)) > 0)
{
n = write(datos2, buf, j);
i = i + n;
if ((size - i) < BS)
{
j = size - i;
}
}
close(datos1);
close(datos2);
}
}
}
}
}
close(dir1);
close(dir2);
return 0;
}

Yep, it seems to work like this:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define BS 512
#define error(a) {perror(a); exit(1);};
int main(int argc, char *argv[]) //argv1 Dir1 argv2 Dir2 argv3 Fich argv4 Pos
{
DIR *dir1;
DIR *dir2;
struct dirent *lectura1;
struct dirent *lectura2;
struct stat st;
int datos1;
int datos2;
int size;
char path[256] = "";
char path2[256] = "";
char temp[256];
char buf[BS];
int j;
int i;
if(argc != 5)
{
error("Numero de argumentos incorrecto");
}
int Pos = atoi(argv[4]);
if(Pos < 0)
{
error("Pos must be 0 or greater")
}
if((dir1 = opendir(argv[1])) == NULL){error("Failed to open origin dir");}
if((dir2 = opendir(argv[2])) == NULL){error("Failed to open destiny dir");}
while((lectura1 = readdir(dir1)) != NULL)
{
sprintf(path, "%s/%s", argv[1], lectura1->d_name);
sprintf(path2, "%s/%s", argv[2], lectura1->d_name); //<-- changed param
if (strcmp(lectura1->d_name, "..") != 0 && strcmp(lectura1->d_name, ".") != 0)
{
if (stat(path, &st) == 0)
{
if (S_ISREG(st.st_mode)) //If is a regular file
{
if((datos1 = open(path, O_RDONLY, 00600)) == -1){error("Failed to open file");} //Opens the target file of Dir1 to copy inside Dir2
size = lseek(datos1,0,SEEK_END);
if (size > Pos) //Check if the size of the file is bigger than the position that indicates the point from which to start copying the file
{
lseek(datos1,Pos,SEEK_SET); //Moves the pointer to the start position of the file1
if((datos2 = open(path2, O_CREAT|O_WRONLY, 00200)) == -1){error("Error al abrir archivo copia");}
lseek(datos2,0,SEEK_SET);
j = BS;
i = 0;
int n = 0;
if ((size - i) < BS)
{
j = size - i;
}
while ((n = read(datos1, buf, BS)) > 0)
{
n = write(datos2, buf, j);
i = i + n;
if ((size - i) < BS)
{
j = size - i;
}
}
close(datos1);
close(datos2);
}
}
}
}
}
closedir(dir1);
closedir(dir2); // <-- changed call
return 0;
}

Related

files are not sorting in C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
// This program is going to scan all files in the current directory. It will make a tree for every folder
// and the folder will have a subsection of files in the tree format. YES SORTING!
char **word;
int folder[1000];
int filecheck[1000];
int coun = 0;
int e = 0;
int f = 0;
int u = 0;
int p = 20;
void printdir(char *dir, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if((dp = opendir(dir)) == NULL)
{
fprintf(stderr,"cannot open directory: %s\n", dir);
return;
}
chdir(dir);
while((entry = readdir(dp)) != NULL)
{
lstat(entry->d_name,&statbuf);
if (S_ISDIR(statbuf.st_mode)) // Check if it's a directory
{
/* Found a directory, but ignore . and .. */
if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)
{
continue;
}
word[coun] = malloc(strlen(entry->d_name) + 1);
folder[e] = coun; // Mark where the folder is.
e++;
f++;
strcpy(word[coun++], entry->d_name);
/* Recurse at a new indent level */
printdir(entry->d_name,depth+1);
f--;
}
else
{
if (f == 0)
{
filecheck[u] = coun;
u++;
}
word[coun] = malloc(strlen(entry->d_name) + 1);
strcpy(word[coun++], entry->d_name);
}
}
chdir("..");
closedir(dp);
}
int main(int argc, char* argv[])
{
word = calloc(1000, sizeof(*word));
printdir(".", 0);
printf("now, print the words in the order.\n");
int c = 0;
int l = 0;
for (int i = 0; i < coun; ++i) // Start readjusting the array in alphabetical order.
{
if (i == folder[c]) // If i matches with a folder, then increment and skip sorting.
{
c++;
}
else // If next is a file, then start the sorting.
{
int imin = i;
for (int j = i + 1; j < folder[c]; ++j) // Keep sorting until the folder ends.
{
char word1[1000], word2[1000];
strcpy(word1, word[j]);
strcpy(word2, word[imin]);
for(int p = 0; word1[p]; p++)
{
word1[p] = tolower(word1[p]);
}
for(int p = 0; word2[p]; p++)
{
word2[p] = tolower(word2[p]);
}
if (strcmp(word1, word2) < 0)
{
imin = j;
}
}
char *tmp = word[i];
word[i] = word[imin];
word[imin] = tmp;
}
}
c = 0;
l = 0;
printf(".\n");
for (int i = 0; i < coun; ++i) // Print the array in the specified format.
{
if (i == folder[c]) // If the folder is the same, print start of the folder.
{
printf("- %s\n", word[i]);
c++;
}
else if (i == filecheck[l]) // If it's a file, print the file normally.
{
printf("- %s\n", word[i]);
l++;
}
else // Print the file inside the folder.
{
printf(" - %s\n", word[i]);
}
}
exit(0);
}
My program is supposed to print the current directory in the tree format. It goes through the sorting perfectly fine, except for the final folder it's checking. For some reason, the hw2 works fine, but hw1 does not sort.
now, print the words in the order.
.
- hw2
- find.c
- ls.c
- Makefile
- tree.c
- hw1
- grep.c
- factor.c
- uniq.c
- monster.c
- sort.c
- tree.c
- tree
I feel like I'm missing something, but I can't find out how to make it work. I've tried different methods and non have worked. Is there anything I can do?

How to list files within a directory that is within a directory in C?

I am trying to list the files inside a directory to a particular level which is specified by the user.
The main issue which I am facing is that I think is that the sub-directories are not recognised as a directory. Thus I tried appending the string to the upper level of a directory. But it doesn't seem to be working.
Here is the directory structure generated using ls -R (All dir* are directories):
dir1 dir2 dir3 listDirectory listDirectory.c
./dir1:
dir1.1 dir1.2 dir1.3
./dir1/dir1.1:
dir1.1.1
./dir1/dir1.1/dir1.1.1:
./dir1/dir1.2:
./dir1/dir1.3:
./dir2:
dir2.1 dir2.2 dir2.3
./dir2/dir2.1:
./dir2/dir2.2:
./dir2/dir2.3:
./dir3:
Here is the code:
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <regex.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct stat s;
regex_t regex;
const char *expression = "^[.]*$";
int reti;
//Directory listing main loop
int listDirectory(int counter,int level,char arr[200]){
printf("Here Counter = %d and Level = %d\n", counter, level);
//Check if the counter is equal to level. If yes exit
if(counter >= level){
return 0;
}
char *currentDirctory = arr;
// printf("%s\n",currentDirctory);
struct dirent *de; // Pointer for directory entry
DIR *dr = opendir(currentDirctory); // opendir() returns a pointer of DIR type.
if (dr == NULL) // opendir returns NULL if couldn't open directory
{
printf("Could not open current directory");
return 0;
}
//Read the contents of the directory
while ((de = readdir(dr)) != NULL){
int size = 0;
struct stat statbuf;
char *x = de->d_name; //The name of each file or folder
char c2[100];
strcpy(c2,x);
strcpy(arr,c2);
//Replace the content of arr with that of new directory or file name
reti = regexec(&regex, arr, 0, NULL, 0);
//Check if the file doesn't match . or .. which is the parent and grand-parent directory
if(!reti){
//If it matches check for next file
continue;
}
else if(reti == REG_NOMATCH){
printf("%s\n",arr);
//Check if the file or the path is a direcfory
stat(arr, &statbuf);
if(S_ISDIR(statbuf.st_mode)){
//If it is a directory then increase the counter and size and put the directory in loop for next call
counter += 1;
listDirectory(counter,level, arr);
size += 1;
}
else{
//It is a file check for next file
continue;
}
counter -= size;
}
}
closedir(dr);
}
int main(){
char arr[200] = "./";
reti = regcomp(&regex, expression, 0);
if(reti) {
fprintf(stderr, "Could not compile regex\n");
}
listDirectory(0,2,arr);
return 0;
}
The output is:
Here Counter = 0 and Level = 2
dir3
Here Counter = 1 and Level = 2
listDirectory.c
dir1
Here Counter = 1 and Level = 2
dir1.1
dir1.3
dir1.2
listDirectory
dir2
Here Counter = 1 and Level = 2
dir2.3
dir2.2
dir2.1
but it should be:
Here Counter = 0 and Level = 2
dir3
Here Counter = 1 and Level = 2
listDirectory.c
dir1
Here Counter = 1 and Level = 2
dir1.1
Here Counter = 2 and Level = 2
dir1.1.1
dir1.2
listDirectory
dir2
Here Counter = 1 and Level = 2
dir2.3
dir2.2
dir2.1
Finally it worked.
I made many changes so don't know what line worked.
So here is the resultant code
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <regex.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct stat s;
regex_t regex;
const char *expression = "^[.]*$";
int reti;
//Directory listing main loop
int listDirectory(int counter,int level,char arr[200]){
printf("Here Counter = %d and Level = %d and directory is %s\n", counter, level, arr);
char c = '/';
size_t len = strlen(arr);
char *str2 = malloc(len + 1 + 1 );
strcpy(str2, arr);
str2[len] = c;
str2[len + 1] = '\0';
//Check if the counter is equal to level. If yes exit
if(counter >= level){
return 0;
}
char *currentDirctory = str2;
// printf("%s\n",currentDirctory);
struct dirent *de; // Pointer for directory entry
DIR *dr = opendir(currentDirctory); // opendir() returns a pointer of DIR type.
if (dr == NULL) // opendir returns NULL if couldn't open directory
{
// printf("\nCould not open current directory\n");
return 0;
}
char root[100];
strcpy(root,str2);
//Read the contents of the directory
while ((de = readdir(dr)) != NULL){
int size = 0;
struct stat statbuf;
char *x = de->d_name; //The name of each file or folder
char c2[100];
strcpy(c2,x);
strcpy(currentDirctory,c2);
//Replace the content of arr with that of new directory or file name
reti = regexec(&regex, currentDirctory, 0, NULL, 0);
//Check if the file doesn't match . or .. which is the parent and grand-parent directory
if(!reti){
//If it matches check for next file
continue;
}
else if(reti == REG_NOMATCH){
//Check if the file or the path is a direcfory
// printf("\nRoot is %s\n",str2);
stat(arr, &statbuf);
// if(S_ISDIR(statbuf.st_mode)){
//If it is a directory then increase the counter and size and put the directory in loop for next call
// printf("%s %s\n",arr,str2);
counter += 1;
size_t len = strlen(root);
size_t len2 = strlen(currentDirctory);
char *str3 = malloc(len + len2 + 1 );
strcpy(str3, root);
strcat(str3,currentDirctory);
// str3[len] = currentDirctory;
str3[len2 + len + 1] = '\0';
// printf("\nGoing into loop directory is %s root is %s\n",str3,root);
listDirectory(counter,level, str3);
size += 1;
// }
// else{
//It is a file check for next file
// continue;
// }
counter -= size;
}
}
closedir(dr);
}
int main(){
char arr[200] = ".";
reti = regcomp(&regex, expression, 0);
if(reti) {
fprintf(stderr, "Could not compile regex\n");
}
listDirectory(0,3,arr);
return 0;
}

C AES not decrypting binary files

I have created two C-functions to encrypt and decrypt entire folders.
#include "myaes.h"
#define SUFFIX ".crypt" //the file suffix for encrypted files
#define MASTER "6ADAC6D678CF49EEF4BB9C16A61F4"
int aesEncryptDir(const char *d)
//encrypts every file in directory d
{
AES_KEY key;
DIR *dp = opendir(d);
FILE *fp,*fp_c;
struct dirent *entry;
char fullpath[strlen(d) + 300];
char cryppath[strlen(fullpath) + 20];
char buffer[10000];
void *in = malloc(16);
void *out = malloc(16);
int sz;
size_t s_read;
if(AES_set_encrypt_key(MASTER,256,&key) != 0)
return -1;
const AES_KEY *static_key = &key;
if(!dp) //could not dir file pointer, maybe the folder does not exist
return -1;
while(entry = readdir(dp))
{
if(strncmp(entry->d_name,".",1) != 0 && strncmp(entry->d_name,"..",2) != 0)
{
memset(fullpath,0,sizeof(fullpath));
memset(cryppath,0,sizeof(cryppath));
memset(buffer,0,sizeof(buffer));
snprintf(fullpath,sizeof(fullpath),"%s/%s",d,entry->d_name);
snprintf(cryppath,sizeof(fullpath),"%s%s",fullpath,SUFFIX);
if(strstr(fullpath,SUFFIX) != NULL)
continue;
fp = fopen(fullpath,"r+");
fp_c = fopen(cryppath,"w");
fseek(fp,0L,SEEK_END);
sz = ftell(fp);
rewind(fp);
fwrite(&sz,sizeof(int),1,fp_c);
while((s_read = fread(buffer,1,1000,fp)))
{
for(int v = 0; v < s_read; v+= 16)
{
memcpy(in,buffer+v,16);
AES_encrypt(in,out,static_key);
fwrite(out,1,16,fp_c);
}
}
}
fclose(fp);
remove(fullpath);
fclose(fp_c);
}
if(closedir(dp) != 0)
return -1;
free(in);
free(out);
return 0;
}
int aesDecryptDir(const char *d)
//decrypts every file in directory d
{
AES_KEY key;
DIR *dp = opendir(d);
FILE *fp,*fp_c;
struct dirent *entry;
char fullpath[strlen(d) + 300];
char comppath[strlen(d) + 300];
char recoverpath[strlen(fullpath)];
char buffer[10000];
int sz = 0;
void *in = malloc(16);
void *out= malloc(16);
if(AES_set_decrypt_key(MASTER,256,&key) != 0)
return -1;
const AES_KEY *static_key = &key;
if(!dp) //could not dir file pointer, maybe the folder does not exist
return -1;
while(entry = readdir(dp))
{
if(strncmp(entry->d_name,".",1) != 0 && strncmp(entry->d_name,"..",2) != 0)
{
memset(fullpath,0,sizeof(fullpath));
memset(recoverpath,0,sizeof(recoverpath));
snprintf(fullpath,sizeof(fullpath),"%s/%s",d,entry->d_name);
strcpy(comppath,fullpath);
if(strstr(comppath,SUFFIX) == NULL)
continue;
strcpy(recoverpath,fullpath);
recoverpath[strlen(fullpath) - strlen(SUFFIX)] = '\0';
fp = fopen(fullpath,"r+");
fp_c = fopen(recoverpath,"w");
fread(&sz,sizeof(int),1,fp);
while(fread(in,16,1,fp))
{
AES_decrypt(in,out,static_key);
fwrite(out,(sz>=16)?16:sz,1,fp_c);
sz-=16;
}
fclose(fp);
fclose(fp_c);
}
}
if(closedir(dp) != 0)
return -1;
free(in);
free(out);
return 0;
}
myaes.h
#ifndef MYAES_H
#define MYAES_H
#include <dirent.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
int aesEncryptDir(const char *d);
int aesDecryptDir(const char *d);
#endif
If i now run a plain text file through aesEncryptDir and then aesDecryptDir, it comes out unchanged. A diff also indicates no changes. A binary file (.jpg) however gets corrupted in the process.
Why does this happen? Has it got something to do with the encoding of the binary files? Do I have to handle binary files differently for en-/decryption?

How to count only the number of directories from a path

I am trying to count only the directories from a path, but it doesn't work. So, i don't want to number both files and directories, i want only the directories. Could you help me, please?
The code:
int listdir(char *dir) {
struct dirent *dp;
struct stat s;
DIR *fd;
int count = 0;
if ((fd = opendir(dir)) == NULL) {
fprintf(stderr, "listdir: can't open %s\n", dir);
}
while ((dp = readdir(fd)) != NULL) {
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
stat(dp->d_name, &s);
if (S_ISDIR(s.st_mode))
count++;
}
closedir(fd);
return count;
}
your stat() call will fail, since you are not in the correct directory. This you can solve by either changing the current directory, or generate full paths and give to stat as argument.
Some Unixes, you can optimize away the stat call by looking at struct dirent, the d_type field
int listdir(char *dir) {
struct dirent *dp;
struct stat s;
DIR *fd;
int count = 0;
if ((fd = opendir(dir)) == NULL) {
fprintf(stderr, "listdir: can't open %s\n", dir);
}
chdir (dir); /* needed for stat to work */
while ((dp = readdir(fd)) != NULL) {
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
#ifdef _DIRENT_HAVE_D_TYPE
switch (dp->d_type)
{
case DT_UNKNOWN:
stat(dp->d_name, &s);
if (S_ISDIR(s.st_mode)) count++;
break;
case DT_DIR:
count++;
break;
}
#else
stat(dp->d_name, &s);
if (S_ISDIR(s.st_mode)) count++;
#endif
}
closedir(fd);
return count;
}
I think you want...
written in C
count the number of directoriesfrom a path.
the counting function will returns int value.
I have no idea about your environment, so it is just a example solution.
If you can use glob, it is so easy to count the number of directories. that is: main.c
#include <stdio.h>
#include <glob.h>
#include <string.h>
#define MAX_PATH 1023
int countDirectories(char* dir)
{
char path[MAX_PATH] = "";
strcat(path, dir);
strcat(path, "/*");
glob_t globbuf;
long i, count = 0;
if (glob(path, GLOB_NOSORT | GLOB_ONLYDIR, NULL, &globbuf) == 0)
{
count = globbuf.gl_pathc;
for (i = 0; i < globbuf.gl_pathc; i++)
{
count += countDirectories(globbuf.gl_pathv[i]);
}
}
globfree(&globbuf);
return count;
}
int main(int argc, char* argv[])
{
int count;
if (argc > 1)
{
count = countDirectories(argv[1]);
}
else
{
count = countDirectories(".");
}
printf("there are %d directories.\n", count);
return 0;
}
and you can try this like:
> gcc main.c -o testglob
> ./testglob /path/to/target/dir
then you'll receive output like this:
path = /path/to/target/dir/*, there are N directories
thanks.

How to get total size of subdirectories in C?

Is there a way to get the total size of subdirectories with recursivity?
For example:
Dir1
-- FileA.txt (90)
-- SubDir2 (4096)
---- FileB.txt (100)
---- FileC.txt (400)
When I try to get the size of SubDir2, it gives me 4186. The expected answer I wish to get is 4596.
My program counts the size of FileA instead of FileB and FileC. How to make it count FileB and FileC?
To start, I have to use these headers:
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
Then, I made this function to call it recursively:
static DIR *dir;
void goDir(char* argv[])
{
struct dirent *dit;
struct stat st;
int size = 0;
static int total_size = 0;
char filePath[NAME_MAX];
while ((dit = readdir(dir)) != NULL)
{
sprintf(filePath, "%s/%s", argv[1], dit->d_name); // To show correctly the size and name of files
lstat(filePath, &st);
// To skip . and ..
if ( (strcmp(dit->d_name, ".") == 0) || (strcmp(dit->d_name, "..") == 0) ) continue;
size = st.st_size;
if(S_ISDIR(st.st_mode))
{
goDir(argv); // For Recursivity
total_size += size;
printf("DIR\t");
printf("MODE: %lo\t", (unsigned long) st.st_mode);
printf("SIZE: %d\t", total_size);
printf("%s\n", dit->d_name);
}
else
{
total_size += size;
printf("FILES\t");
printf("MODE: %lo\t", (unsigned long) st.st_mode);
printf("SIZE: %d\t", size);
printf("%s\n", dit->d_name);
}
}
}
And then, my main program:
int main (int argc, char *argv[])
{
if ( argc != 2 ) {
printf("Usage: Program <Directory>\n");
return 1;
}
if ((dir = opendir(argv[1])) == NULL) return 1;
goDir(argv);
closedir(dir);
return 0;
}
Your goDir() function never opens a new directory, or closes the directory once it has finished. That is going to lead to problems — basically, you are not traversing down your directory hierarchy.
You'll need to make dir a local (non-static) variable in the goDir() function; you'll open and close directories; and instead of passing argv, you'll pass a directory name, etc.
While you're at it, you should change goDir() to return the size it finds, and lose the static variable total_size.
This code looks semi-plausible:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#ifndef NAME_MAX
#define NAME_MAX 1024
#endif
static long goDir(char *dirname)
{
DIR *dir = opendir(dirname);
if (dir == 0)
return 0;
struct dirent *dit;
struct stat st;
long size = 0;
long total_size = 0;
char filePath[NAME_MAX];
while ((dit = readdir(dir)) != NULL)
{
if ( (strcmp(dit->d_name, ".") == 0) || (strcmp(dit->d_name, "..") == 0) )
continue;
sprintf(filePath, "%s/%s", dirname, dit->d_name);
if (lstat(filePath, &st) != 0)
continue;
size = st.st_size;
if (S_ISDIR(st.st_mode))
{
long dir_size = goDir(filePath) + size;
printf("DIR\t");
printf("MODE: %lo\t", (unsigned long) st.st_mode);
printf("SIZE: %ld\t", dir_size);
printf("%s\n", filePath);
total_size += dir_size;
}
else
{
total_size += size;
printf("FILES\t");
printf("MODE: %lo\t", (unsigned long) st.st_mode);
printf("SIZE: %ld\t", size);
printf("%s\n", filePath);
}
}
return total_size;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <Directory>\n", argv[0]);
return 1;
}
long size = goDir(argv[1]);
printf("Total size: %ld\n", size);
return 0;
}
It compiles and runs. It does not give the same answer as du -k, mainly because it does not round up the size of files to an integral number of disk blocks. You'd need to look at st_blksize and/or st_blocks in the struct stat to get that information.
You'll have to use a hash table to keep track of the occurrences of inodes. So that they are not counted twice.

Resources