I am trying to make a program that returns the total size of a directory. The program takes the path to the directory, parses it, if it finds a file(done using a function) it adds the size, else
I recall the function. After some debugging i found out that the line containing the call to the recursive function give a segmentation fault and i have absolutely no idea how to fix it.
my code
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
int isDirectory(const char* fileName) {
DIR* dir=opendir(fileName);
if(dir!=NULL) {
closedir(dir);
return 1;
} else if(errno == ENOTDIR) {
return 0;
} else return -1;
closedir(dir);
}
int getFileSize(char* fileName) {
FILE* file;
file=fopen(fileName,"r");
fseek(file,0,SEEK_END);
int size=ftell(file);
fclose(file);
return size;
}
int getAllSize(char* dirName) {
DIR* dir;
char* name=dirName;
int size=0;
struct dirent *dent;
dir=opendir(dirName);
if(dir!=NULL) {
while((dent=readdir(dir))!=NULL) {
char help[1000000];
memset(help,0,sizeof help);
if(strcmp(dent->d_name,"..") && strcmp(dent->d_name,".")) {
strcat(help,name);
strcat(help,"/");
strcat(help,dent->d_name);
printf("%s\n",help);
if(isDirectory(help)==1) {
getAllSize(name);
} else{
printf("before %d\n",size);
size+=getFileSize(help);
printf("after %d\n",size);
}
}
}
} else {
printf("sal1\n");
}
closedir(dir);
printf("%d",size);
return size;
}
int main(int argc,char** argv) {
getAllSize("/home/rares/Documents/OS/Lab3");
return 0;
}
Related
#include <unistd.h>
#include <pwd.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
uid_t userIdFromName(char *name)
{
struct passwd* pwd;
pwd=getpwnam(name);
if(pwd==NULL)
{
perror("gepwnam\n");
exit(EXIT_FAILURE);
}
return pwd->pw_uid;
}
int main(int argc, char* argv[])
{
uid_t uid;
int totalEntries=0;
DIR* dir;
struct dirent* newFile;
char strUID[65];
if(argc<1)
{
fprintf(stderr,"The format is: %s name",argv[0]);
exit(EXIT_FAILURE);
}
uid=userIdFromName(argv[1]);
dir=opendir("/proc/");
sprintf(strUID,"%d",uid);
while((readdir(dir))!=NULL)
{
totalEntries++;
}
char* dirNames[1000];
char* dirIds[1000];
int newCount=0;
dir=opendir("/proc/");
while((newFile=readdir(dir))!=NULL)
{
char statusFilePath[65]="/proc/";
strcat(statusFilePath,newFile->d_name);
strcat(statusFilePath,"/status");
FILE* statusFile=fopen(statusFilePath,"r");//one of the file has been opened;
size_t size;
char* lineData;
if(statusFile==NULL)
continue;
int currentPoisition=0;
while((getline(&lineData,&size,statusFile))!=-1)
{
if(strncmp("Uid:",lineData,strlen("Uid:"))==0)
{
char* dataLine;
currentPoisition=ftell(statusFile);
fseek(statusFile,0,SEEK_SET);
if(strstr(lineData,strUID)!=NULL)
{
int forName=0,forPid=0;
while((getline(&dataLine,&size,statusFile))!=-1)
{
if(strncmp("Name:",dataLine,strlen("Name:"))==0)
{
printf("%s\n",dataLine);
dirNames[newCount]=dataLine;
forName=1;
}
if(strncmp("Pid:",dataLine,strlen("Pid:"))==0)
{
printf("%s\n",dataLine);
dirIds[newCount]=dataLine;
forPid=1;
}
if(forName==1&&forPid==1)
{
newCount++;
}
}
}
fseek(statusFile,0,SEEK_SET);
fseek(statusFile,currentPoisition,SEEK_SET);
}
}
}
/* int runner=0;
while(runner<newCount)
printf("%s\n",dirNames[runner++]);*/
}
I have been unable to understand the core-dumps generated for this program.The program crashes halfway. Here is the core-dump info:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f4ed8699d9c in _nss_files_getpwnam_r (name=0x0, result=0x7f4ed8896140 , buffer=0x559f75c7e2a0 "root", buflen=1024, errnop=0x7f4ed889a4c0) at nss_files/files-pwd.c:32
32 nss_files/files-pwd.c: No such file or directory.
I thank you for your help.
Have you qualified the contents of argv[1] before using it here?
uid=userIdFromName(argv[1]);
Also, among other issues, using a variable created as:
char* lineData;
in a function such as:
while((getline(&lineData,&size,statusFile))!=-1)
Will likely cause a seg-fault, as you are attempting to write to a location that you do not own.
Same for:
char *dataLine;
...
while((getline(&dataLine,&size,statusFile))!=-1)
etc.
Create memory and an address for these (and any other like them) before using.
eg:
size_t size = 1000;
char *lineData = malloc(size*(sizeof(*lineData));
if(lineDate)
{
//continue to use lineData
free(lineData);//when done using it
...
I type this code to get the home directory. I have later edited it to include all of the code:
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdarg.h>
#include "anotherfile.h"
typedef unsigned int uint;
void Interval(void) {
static uint S = 0;
static uint C = 0;
static uint M = 0;
static uint D = 0;
usleep(10e5/0x20);
printf("%d\n", C);
printf("%d\n", S);
printf("%d\n", M);
if(C == 0x20) {
if(S == 59) {
S=0;
M++;
}else{S++;}
C=0;
}else{C++;}
Interval();
}
int main(int argc, const char *argv[]) {
char *HomeDir;
if((HomeDir = getenv("HOME")) == NULL) {
HomeDir = getpwuid(getuid())->pw_dir;
if(HomeDir == NULL) {
printf("Failed to get Home Directory\n");
}else{printf("Retry Home Directory Found\n");}
}else{printf("Success getting Home Directory\n");}
Interval();
return 0;
}
It gives me the implicit declaration warning. It says something is wong with the getenv partHow can I fix it?
The function getenv is declared in stdlib.h according to this reference. So you need to add
#include <stdlib.h>
I'm new to the subject of splitting files and header files in C.
I get a Segmentation fault (core dumped) when i'm trying to run main. I don't get any more errors.
I tried to trace the problam and I think it is the line:
syntax_check(fp, symb_table, &IC, &DC); in the main.c.
I'm just trying to pass from main.c the parameters *fp and another array strcture(symbol[]) to a function in syntax_check(in syntax_check.c) and do some actions.
main.c:
#include "main.h"
int main()
{
FILE *fp;
int DC=0;
int IC=100;
symbol symb_table[20];
if (!(fp=fopen("file.txt", "r")))
{
printf("Error opening file");
exit(0);
}
syntax_check(fp, symb_table, &IC, &DC);
fclose(fp);
return 0;
}
main.h:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char name[10];
int address;
int external;
int action;
} symbol;
int syntax_check(FILE*, symbol[], int*, int*);
syntax_check.c:
#include "syntax_check.h"
int syntax_check(FILE *fp, symbol symb_table[], int *IC, int *DC)
{
char buff[80]; /*line to read*/
char buff2[20]; /**/
int i=0;
fgets (buff, 80, fp);
while (buff[i]!='\0'||buff[i]!=' '||buff[i]!='\t')
{
buff2[i]=buff[i];
i++;
}
buff[i]='\0';
if (exist(buff2))
printf("legal");
else
printf("illegal");
return 0;
}
syntax_check.h:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char name[10];
int address;
int external;
int action;
} symbol;
FILE *fp;
int exist(char action[]);
have to write a program displaying list of all logged users (their id and groups if -i or -g is used) using shared library. The functions in shared library are working correctly, but it seems like function pointer causes segmentation fault. Since it's a school assigment I have to use C and functions have to return nothing, and take only user name. I'm quite new to programming in linux (obviously).
main code:
#include <unistd.h>
#include <stdlib.h>
#include <utmp.h>
#include <dlfcn.h>
struct utmp *p;
int main(int argc, char* argv[]){
int opt, iflag = 0;
int gflag = 0;
void *handle;
while((opt = getopt(argc, argv, "ig")) != -1)
{
switch(opt)
{
case 'i':
iflag = 1;
break;
case 'g':
gflag = 1;
break;
default:
fprintf(stderr, "Błąd \n");
exit(EXIT_FAILURE);
}
}
handle = dlopen("./zad2lib.so", RTLD_LAZY);
if (handle == NULL) {
fprintf(stderr, "Unable to open library: %s\n", dlerror());
iflag = 0;
gflag = 0;
}
while ((p = getutent()) != NULL) {
if (p->ut_type == USER_PROCESS)
{
if (iflag == 1) {
dlerror();
void (*func)(char*) = (void(*)())dlsym(handle, "userID");
func(p->ut_user);
}
printf("%s ", p->ut_user);
if (gflag == 1) {
dlerror();
void (*func)(char*) = (void(*)())dlsym(handle, "userGroups");
func(p->ut_user);
}
}
printf("\n");
}
dlclose(handle);
}
return 0;
}
.so file:
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
void userID(char *name) {
struct passwd *pw = getpwnam(name);
printf("%d ", pw->pw_uid);
}
void userGroups(char *name) {
struct passwd *pw = getpwnam(name);
int i;
int gidsize = 100;
struct group* g;
gid_t *grouplist = malloc(gidsize*sizeof(gid_t));
getgrouplist(name, pw->pw_gid, grouplist, &gidsize);
printf("[");
for (i = 0; i < gidsize; i++) {
g = getgrgid(grouplist[i]);
printf(" %s", g->gr_name);
}
printf(" ]");
free(grouplist);
}
How do I use scandir, so that it only fills my struct dirent ** namelist, with folders?
You can filter the entities to list by providing a filter function, which should return a non-zero value if the file is to be included in the list.
Unfortunately, the members of the dirent struct don't tell you whether you have a directory or not (although your system might include a type field), so you must use some other means to find directories, for example stat:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int filter_dir(const struct dirent *e)
{
struct stat st;
stat(e->d_name, &st);
return (st.st_mode & S_IFDIR);
}
You could also try to call opendir on the name and check wheter that succeeds. (But don't forget to close it if it is successful.)
This works for the current directory, because the names exclude the path. The filter also doesn't provide a slot for passing additional data, so the best you can do is to define a global variable that holds the path and that you must set beforehand.
Here's an implementation with a wrapper function, scandir_dir:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
static const char *filterdir;
static int filter_dir(const struct dirent *e)
{
char buf[NAME_MAX];
struct stat st;
if (filterdir) {
snprintf(buf, sizeof(buf), "%s/%s", filterdir, e->d_name);
stat(buf, &st);
} else {
stat(e->d_name, &st);
}
return (st.st_mode & S_IFDIR);
}
int scandir_dir(const char *path, struct dirent ***namelist)
{
int n;
filterdir = path;
n = scandir(path, namelist, filter_dir, alphasort);
filterdir = NULL;
return n;
}
int main()
{
struct dirent **namelist;
int n;
n = scandir_dir("/some/dir", &namelist);
if (n < 0) {
perror("scandir");
} else {
int i;
for (i = 0; i < n; i++) {
printf("%s\n", namelist[i]->d_name);
free(namelist[i]);
}
free(namelist);
}
return 0;
}