C trouble with stat - c

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

Related

How to find file in directory in c

I'm trying to create a function in c which scans the given directory for files of the given format (for example :- _sort.txt) and check if the directory contains that format file or not.
if directory contain file of that format then it should return -1 else 0.
but i am stuck on how to scan the directory.can anyone help me with this.
i am fairly new to c so please bear with me.
operating system :- Linux
you can use strstr to find the pattern in the filename.
don't forget to include these headers:
#include <dirent.h>
#include <string.h>
int find_file(const char *pattern, DIR *dr) {
struct dirent *de;
int found = -1;
while ( (de = readdir(dr)) != NULL) {
// DT_REG is a regular file
if (de->d_type == DT_REG && strstr(de->d_name, pattern) != NULL) {
found = 0;
break;
}
}
return found;
}
any where that you want to use this function you should pass the DIR which is opened with opendir.
int main() {
DIR *d = opendir(".");
const char *pattern = "_sort.txt";
if (find_file(pattern, d) == 0)
printf("found it\n");
else
printf("not found it\n");
return 0;
}
for further information about dirent struct:
man readdir

How do I read a file directory in C to get the Names of all non-folder files

I am trying to read a given directory filePath and get the names of all non folder files into a array of strings. So the issue that I need solved is how to specifically not get folder type files but also get all the other file type names and store them into the string array. Later I plan to use threads to read these individual files as well, but I need to be able to store the files names properly. The code that I am currently using is below. It should also be noted that this code is being executed by a child process from the fork() command, but I am not sure if that is relevant to the issue anyway. Any help would be appreciated. Thanks.
Example:
In the Home/Documents there are 4 files: hello.txt something.dat folder1 something2.dat
My string array should have the values hello.txt, something.dat, and something2.dat
Note: It is okay for me not to do the files as a I go through the directory as the files themselves are not going to be changed at all content wise.
//char* directory is an absolute filePath to the directory
void getFilesFromDirectory(char* directory, pid_t process)
{
int index =0;
DIR *dir;
struct dirent *ent;
//Can hold only 500 valid files in the folder
char *stringArray[500];
if ((dir = opendir (directory)) != NULL)
{
while ((ent = readdir (dir)) != NULL)
{
strcpy(stringArray[index],ent->d_name);
index++;
}
closedir (dir);
}
else
{
/* could not open directory */
perror ("");
}
//Everything Below is not related to the problem. Just what I am using it for.
pthread_t threadArray[index];
pthread_t senderThread;
//thread_param_t parameterSender;
thread_param_t paramterArray[index];
sem_init(&empty,0,bufferSize);
sem_init(&full, 0, 0);
sem_init(&mutex, 0, 1);
//parameterSender.listItem = listHead;
pthread_create(&senderThread, NULL, senderFunction, NULL);
//int threadCounter = 0;
for(int i =0; i<index; i++)
{
paramterArray[i].fileLocation = strcat(directory, stringArray[i]);
pthread_create(&threadArray[i], NULL, threadFunction, paramterArray + i);
}
}
You could check stringArray for files without "." and set this pointer to Null. (There are files missing)
A better option is this:
#include <stdio.h>
#include <dirent.h>
int main()
{
DIR *folder;
struct dirent *entry;
int files = 0;
folder = opendir(".");
if(folder == NULL)
{
perror("Unable to read directory");
return(1);
}
printf("debug\n");
while( (entry=readdir(folder)) )
{
files++;
printf("File %3d: %s :: %s\n",
files,
entry->d_name,
(entry->d_type == DT_DIR)?"Directory" : "File"
);
}
closedir(folder);
return(0);
}

writing ls from scratch recursively

I am working on a simple project to implement "ls -R" from scratch. Whenever I run what I have, my program just keeps searching the root directory over and over again. What am I doing wrong?
void lsR(char dirName[]) {
/*
The recursive function call.
*/
DIR *dir;
struct dirent *directory;
struct stat fileStat;
char type;
char **nameList[MAX_RECURSIVE_FILES];
struct passwd *user;
int count = 0;
int i = 0;
printf("\n");
printf("./%s :\n", dirName);
printf("\n");
if ((dir = opendir(dirName)) == NULL) {
perror("opendir error:");
return;
}
while ((directory = readdir(dir)) != NULL) {
if (stat(directory->d_name, &fileStat) < 0) {
perror("fstat error:");
return;
}
if (fileStat.st_uid == 1) {
continue;
}
user = getpwuid(fileStat.st_uid);
printf("%s ", directory->d_name);
fileType(&fileStat, &type);
if ((type == 'd') && (count < MAX_RECURSIVE_FILES)) {
nameList[count] = malloc(sizeof(char)*MAX_STRING_LENGTH);
strncpy(nameList[count++], directory->d_name, MAX_STRING_LENGTH);
}
}
closedir(dir);
printf("\n");
for (i=0; i<count; i++) {
printf("Calling lsR on: %s\n", nameList[i]);
lsR(nameList[i]);
}
}
When it executes, I get the following output:
"./. :
., .., ... all other files in my current working directory ....
./. :
., .., ... all other files in my current working directory...
"
Among the list of files in the current directory you've noticed . and .. The first one is a hardlink to the current directory and the second one to the parent directory. So when you recurse through your dir entries you will want to skip those two. Otherwise the first directory you will recurse into will be ., in other words the directory you've just gone through.
This is the reason of your program current behavior, but once you fix that you will run into the issue lurker mentioned in his answer.
Additional notes :
Are you sure about the char **nameList[MAX_RECURSIVE_FILES]; variable? Seems to me you want an array of char * not an array of char **.
Are you aware you can use the S_ISDIR macro on the st_mode field of your stat struct, in order to check that the current file is not a directory instead of your custom function?
You need to include the path relative to your program's current directory. Each nameList element will need to be dirName + "/" + directory->d_name.
If you started out calling lsR on the local directory, ./foo and foo has directory named bar under it, then to open bar you need to open ./foo/bar since your program is running from the directory represented by ..

stat outputting the wrong values for files in a directory

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

Delete files from a specific folder in C

I'm trying to delete files from a specifc folder. My deleteFile() function only deletes on its home folder, not on /tmp folder which is what I need. I tried the same approach as my displayDIR() function to change directory but I can't figure out how to make it work. I use cygwin as compiler.
void deleteFile() {
int status;
char filetodelete[25];
printf("\n \t **Delete File**\n");
displayDIR();
printf("\n\tChoose the name of the file to delete:\t");
scanf("%s", filetodelete);
status = remove(filetodelete);
if( status == 0 )
printf("%s file deleted successfully.\n", filetodelete);
else {
printf("\n\tUnable to delete the file");
perror("\n\tError");
}
}
void displayDIR() {
DIR *d;
struct dirent *dir;
d = opendir("C:/cygwin/tmp");
if (d) {
while ((dir = readdir(d)) != NULL)
printf("\t\t\t%s\n", dir->d_name);
closedir(d);
}
}
You need to include the folder path in the argument to remove():
char fullpath[40] = "C:/cygwin/tmp/";
strcat(fullpath, filetodelete);
status = remove(fullpath);

Resources