im looking for a code who will recursively list all directories and files of a directory given on argument in C programming, ive find an interresting code (below) but I dont understand the snprintf function and particulary the "/",
I would prefer to use strcat or other system function to override the sprintf function but I dont see how since I dont understand what the snprintf do here.
Heres the code:
int is_directory_we_want_to_list(const char *parent, char *name) {
struct stat st_buf;
if (!strcmp(".", name) || !strcmp("..", name))
return 0;
char *path = alloca(strlen(name) + strlen(parent) + 2);
sprintf(path, "%s/%s", parent, name);
stat(path, &st_buf);
return S_ISDIR(st_buf.st_mode);
}
int list(const char *name) {
DIR *dir = opendir(name);
struct dirent *ent;
while (ent = readdir(dir)) {
char *entry_name = ent->d_name;
printf("%s\n", entry_name);
if (is_directory_we_want_to_list(name, entry_name)) {
// You can consider using alloca instead.
char *next = malloc(strlen(name) + strlen(entry_name) + 2);
sprintf(next, "%s/%s", name, entry_name);
list(next);
free(next);
}
}
closedir(dir);
}
from How to recursively list directories in C on LINUX
Okay, my program is running but now i want to save all the file and directory printed to a file like i run my program ./a.out . > buffer where buffer contain what the program should print on the shell
the line
sprintf(next, "%s/%s", name, entry_name);
could be replaced with
strcpy (next, name);
strcat (next, "/");
strcat (next, entry_name);
and it would do the same thing. Does that clarify it for you?
Related
I'm using dirent.h to loop inside dir recursivly.
I want to edit the name of a file then past his data and his new name to a new file.
Here i can loop and edit his name with a new extension (.enc), the only problem is that weird symbol appear between my PATH and my D_NAME (aka "fn" after edit).
Here is my code and an exemple.
while(1)
{
struct dirent *entry;
const char *d_name;
unsigned char d_type;
entry = readdir(d);
if(!entry)
{
// no more entries in this directory -> break the loop
break;
}
d_name = entry->d_name;
d_type = entry->d_type;
if(strcmp(d_name, ".")!=0)
{
if(strcmp(d_name, "..")!=0)
{
if(d_type == DT_REG)
{
if(de_flag=='e')
{
char *fn = NULL;
fn = malloc(400*sizeof(char));
strcat(fn, d_name);
strcat(fn, ".enc");
char abs1_path[PATH_MAX];
snprintf(abs1_path, PATH_MAX, "%s/%s", name, fn);
char ch;
char abs_path[PATH_MAX];
snprintf(abs_path, PATH_MAX, "%s/%s", name, d_name);
printf("%s %s\n", abs1_path, abs_path);
FILE *source, *target;
//source = fopen(abs_path, "r");
//target = fopen(abs1_path, "w");
As u can see, on the first lap of the loop, there is no problem on the new filename
So i think the problem comes from the malloc() or something like this. (i use free(fn)) after, but dont wanted to show ALL the source code.
Is there a way where you can update the char arrays of a base path with an updated path?
struct dirent *dp;
DIR *dir;
struct stat buf;
dir = opendir("./statdir/");
int x;
char base_path[11] = "./statdir/";
char* full_path;
int main(int argc, char* argv[]){
while((dp = readdir(dir)) != NULL) {
full_path = strcat(base_path, dp->d_name);
if((x = lstat(full_path, &buf)) == -1) {
perror("stat failed");
exit(1);
}
printf("Debug: %s\n", full_path);
}
closedir(dir);
return(0);
}
}
My goal is to update full_path after each loop to the base_path + whatever argument is passed to argv[] and in my directory i have two files name file1 and file2....
i.e if I ran my code and wrote ./Stat, I expected full_path to be "./statdir/file1" and then "./statdir/file2"
The results I am getting however is :
Debug: ./statdir/.
Debug: ./statdir/...
stat failed: No such file or directory
You could build the full filename using snprintf like this...
snprintf(full_path, PATH_MAX, "%s/%s",base_path, dp->d_name);
...but you'll first need to ensure that full_path has the space to contain the filename so replace
char *full_path;
with
char full_path[PATH_MAX];
You're concatenating a string onto base_path, however that array is just long enough for what you initialized with. That means you're writing past the end of the array. This invokes undefined behavior.
Also note that full_path is pointing to the start of base_path.
Instead, make full_path an array big enough to hold a full path. Then use strcpy to copy over the base path, then strcat to add on the current entry.
char full_path[100];
...
while((dp = readdir(dir)) != NULL) {
strcpy(full_path, base_path);
strcat(full_path, dp->d_name);
In my program stat is only working for a current directory. Can any one please help me with this.
even though I am passing parameter from main it is only working for current directory.
and source path is good it is printing correct path which I have passed from the main.
DIR *dr;
struct dirent *cur;
struct stat fi;
long int total_size = 0;
dr = opendir(source);
char *name;
printf("%s\n\n\n", source);
if (!(dr))
{
perror("opendir()");
return(1);
}
while (cur = readdir(dr))
{
if(cur->d_name[0] != '.')
{
if(stat(cur->d_name, &fi) == -1)
{
printf("error \n\n");
}
else
{
printf("%s ",cur->d_name);
printf("%ld ",fi.st_blocks);
total_size = total_size + fi.st_blocks;
}
}
}
printf("\n\ntotal_size = %ld \n", total_size);
printf("\n\n\n");
return 0;
}
cur->d_name only contains the file name.
to get a 'stat()' outside the current directory,
need to prefix with the path string.
Also need to check if the returned struct from readdir()
is a file or a sub directory.
The main problem is that stat expects a file path but d_name is just the file name. You can find a working example of how to use stat with d_name here
I am trying to create a function that will take an inputted directory path (filrOrDir) and output info for each file in the directory: file name, size, and last access date. The program compiles and prints everything. It prints the right file names but, for each file, the size and last access date are wrong. I thought maybe it was because of my variable declarations being in the while loop but I moved them around and still go the same results. Can somebody please give me a hint or a tip on what I am doing wrong? Below is my code:
void dirInfo(char *fileOrDir)
{
DIR *d;
struct dirent *dir;
d = opendir(fileOrDir);
while((dir = readdir(d)) !=NULL)
{
struct stat *buffer = (struct stat *)malloc(sizeof(struct stat));
char accessString[256];
char *name = (char *)malloc(sizeof(char));
struct tm *tmAccess;
int size = 0;
name = dir->d_name;
stat(name, buffer);
printf("%s ", name);
size = buffer->st_size;
printf("%d bytes ", size);
tmAccess = localtime(&buffer->st_atime);
strftime(accessString, sizeof(accessString), "%a %B %d %H:%M:%S %Y", tmAccess);
printf("%s\n", accessString);
printf("\n");
free(buffer);
}
closedir(d);
}
name = dir->d_name is the name of the file inside the directory fileOrDir, but
stat(name, buffer);
tries to stat the file name in the current working directory.
That fails (unless fileOrDir happens to be the current working directory),
and therefore the contents of buffer is undetermined.
You have to concatenate the directory and the file name for the stat call.
You should also check the return value of the stat call.
For example:
char fullpath[MAXPATHLEN];
snprintf(fullpath, sizeof(fullpath), "%s/%s", fileOrDir, name);
if (stat(fullpath, buffer) == -1) {
printf(stderr, "stat failed: %s\n", strerror(errno));
} else {
// print access time etc.
}
I've just started learning linux and C, please don't judge me strictly.
I'm trying to find a current working directory and to open file in this directory to find a specific word. It gives correct cwd if I find only cwd, but when I added while loop cwd is null.
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
main(){
char *buff;
char *currentDir =getcwd(buff,PATH_MAX);
printf("Current directory: %s\n",currentDir);
FILE *file;
char *filename = "profile";
file = fopen(filename,"r");
if(file == NULL)
{
fprintf(stderr,"File %s wasn't found\n",filename);
}
while(1)
{
char buffer[80];
char *token;
fgets(buffer,80,file);
if(feof(file))
{break;}
else{
*token = strtok(buffer,"=");
if(strcmp(token,"HOME")==1);
{
printf("HOME token is found");
}
}
free(token);
}
fclose(file);
}
The output:
Current directory: (null)
Segmentation fault
buff is pointing to random memory.
You might like to declare buff like so:
char buff[PATH_MAX] = "";
If on Linux then one can alternatively let getcwd() allocate the memory needed by doing so:
char * currentDir = getcwd(NULL, 0);
currentDir needs to be passed to free() when done with it, and buff is not needed then.
Remove the line:
free(token);
token points into buffer, which is on the stack. So, no need to free it.
Another bug is:
*token = strtok(buffer,"=");
strtok() returns a char*, so this should read:
token = strtok(buffer,"=");
You should also modify your loop to:
#include <string.h>
...
char buffer[80];
while (fgets(buffer,80,file)) {
char *token = strtok(buffer,"=");
if (strcmp(token,"HOME") == 0);
{
printf("HOME token is found");
}
...
Small function to get current directory:
void get_working_dir(void)
{
char buf[PATH_MAX];
if (getcwd(buf, sizeof(buf)) == NULL) {
fprintf(stderr, "Err.:(%d) - %s: curr. workdir\n", errno,strerror(errno));
exit(EXIT_FAILURE);
}
/* print current directory */
printf("%s\n", buf);
}
Invoke function with:
get_working_dir();
I was facing the same problem so i took a look to the man pages where is was said that the getcpw() syscall will malloc the buffer if it is NULL.
I think the problem is that your buffer is not nulled so try to initiallize it with the NULL pointer
char *buff=NULL;
buff=getcwd(buff,PATH_MAX);