stat outputting the wrong values for files in a directory - c

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.
}

Related

Weird symbol after editing filename through dirent

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 proper way to concatenate a base path name with a new path name?

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);

C - remove() - Error 2 (File does not exist), but file exists

In C, I want to delete a file by 1) accepting the file name as input then 2) removing the file.
However, when I supply the name of a file that exists, I get error code 2 from the remove() function ('file does not exist').
I have tried using 1) just the name of the file and 2) the full path of the file. Here is my code:
#include<stdio.h>
#include<errno.h>
#include<dirent.h>
int main()
{
// sanity check; print names of all files in current dir
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
printf("%s\n", dir->d_name); // prints 'testfile.txt' (and others)
}
closedir(d);
}
char buffer[101];
printf("Name of file to delete: ");
char *result = fgets(buffer, 101, stdin);
/*
input tried: 'testfile.txt', 'full/path to/testfile.txt',
'full/path\ to/testfile.txt'
(all less than 101 chars)
*/
if (remove(result) == 0)
printf("File %s deleted.\n", result);
else
printf("%d\n", errno); // always prints 2 ('file does not exist' error)
fprintf(stderr, "Error deleting the file %s\n", result); // as given in input
return 0;
}
Why is remove() failing with error code 2? How can I fix it?

C trouble with stat

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

Can opendir(pathname) change the value of the input pathname?

I've received some curious results while using opendir():
int dtw(char *path) {
struct stat statbuf;
...
else if (S_ISDIR(statbuf.st_mode)) {
printf("Path is: %s\n", path);
struct dirent *dirent;
DIR *dirp;
if ((dirp = opendir(path)) == NULL) {
puts("Can't open directory.");
return -1;
}
printf("Path is: %s\n", path);
}
...
}
Results in:
Path is: /home/.../etc
Path is:
The only thing that would affect path is opendir() here. Does it have side effects that I'm not seeing? Or is there something else at work?
No changes are allowed; the definition of opendir() is:
DIR *opendir(const char *dirname);
And the const says opendir() did not change it.
I wonder if your path is a pointer to freed memory? In that case, the memory may have been allocated to opendir() and you are seeing the change because you're using a dangling pointer to memory that you should not be looking at?

Resources