Trying to open a relative path in Ubuntu doesn't work - c

I'm trying the open a relative path in Ubuntu , but after opening the first folder - called 14 - the code fails to open the folder inside - called 15:
int pathsCtr; // number of folders in RelativeArray
char ** RelativeArray; // the folders in the relative path, currently:
RelativeArray[0] = "14";
RelativeArray[1] = "15";
// some code before
if (pathsCtr > 0 && flag == TRUE) // then we have a relative path
{
int j = 0;
while (j < pathsCtr) // run until the last path and open every one
{
printf("\n%s\n" , RelativeArray[j]);
dirp = opendir(RelativeArray[j]); // open all directories until the last one
if (dirp == NULL)
return -1;
j++; // proceed to the next directory
}
flag = FALSE; // turn off the flag , we'll never go near this again
}
When j == 0 this line : dirp = opendir(RelativeArray[j]); works and dirp is not NULL.
But when j == 1 that line dirp = opendir(RelativeArray[j]); fails and dirp is NULL .
What am I doing wrong?
EDIT:
Assume that I'm doing malloc for RelativeArray before the above code .

opendir() opens a directory for reading its contents, but it does not change the working directory of the process.
To access a subdirectory, you will have to specify it by its fully path relative to the current working directory (or else its absolute path).
You can probably do this by concatenating your strings with an appropriate separator character.
Since you don't seem to do anything with the directory stream pointer returned by opendir() other than check that it's non-null, there's a good chance this is not the function you want to be using. You may want to look at chdir() instead (man 2 chdir) but do think about any undesired consequences.

Related

Remove file from directory - ext-like file system implementation

I have an issue. I'm currently trying to implement an ext-ish file system. I've done the inode operations such as read and write. I've created a structure that represents both a regular file and a directory. I have a problem when trying to remove a certain file from the directory.
char
dirremove(struct dirent *dir, struct dirent *file)
{
dirent_t n = {.mode = NODDIR, .inumber = remdirnod,
.r = 0, .w = 0};
strcpy(n.nm, dir->nm);
dirent_t t;
dir->r = 0;
char r = 1;
while (!dirread(dir, &t))
{
int tt = dir->r;
dir->r = 0;
dirent_t ff[3];
filread(ff, dir, 3 * entrysiz);
dir->r = tt;
if (!strcmp(t.nm, ""))
return 1;
if (!(!strcmp(t.nm, file->nm) && !(r = 0)))
assert(!dirappend(&n, &t));
}
assert(n.w == dir->w - entrysiz);
dir->w = n.w;
dir->r = n.r;
copyinode(dir->inumber, remdirnod);
return r;
}
This is the function called from the rm command. It takes the directory object (where the file is stored) and the file object to be deleted. I know this solution is not the best in terms of speed and memory usage but I'm still a beginner in this area, so don't hate me a lot, please :).
The function is designed to do the following. It has to read all files and check if the current is the one to be deleted. If not, the file is added to a new directory (empty in the beginning) which will replace the old one at the end of the function. The "new" directory is an entry saved entirely for this purpose, so there isn't a chance that all inodes are already used.
The test that I've done is to create a file (works fine), then remove it, then create it again and remove it. Everything works perfectly except for the second execution of the dirremove function. The directory has its dot and dot-dot directories by default so it goes through them first. The result is that the first deletion is successful. Everything works perfectly. But the second time things go wrong somewhere.
int tt = dir->r;
dir->r = 0;
dirent_t ff[3];
filread(ff, dir, 3 * entrysize;
dir->r = tt;
I added the ff array that should read the whole content of the directory and this would help me figure out if the correct files are there. On the first and second iteration, all files (".", ".." and "some-other-file") are there but at the iteration which should hold the object of the file that's to be removed the third file suddenly goes all zeroes.
I've debugged this for several hours but it continues to fail the same way.
Probably I didn't explain the failure the best way, but there are a lot of things that I forgot to say, so if I missed something please don't ignore the question and just ask about it.

Fopen function returns null when given an existing path

When trying to open a file with fopen(path, "2"); i get NULL on an existing path
iv'e tried to enter only the file name and it works but i want the program to write the file in the path...
Yes, i write the path with double backslashes "\\" when it's necesary.
Yes the path without doubt exists.
FILE* log;
char directory_path[PATH_LEN] = { 0 };
char directory_file[PATH_LEN] = { 0 };
//directory_path is the directory, entered by the user
//LOG_NAME is the files name without the path - "log.txt"
//#define PATH_LEN 100
printf("Folder to scan: ");
fgets(directory_path, PATH_LEN, stdin);
directory_path[strlen(directory_path) - 1] = 0;
//this section connects the path with the file name.
strcpy(directory_file, directory_path);
strcat(directory_file, "\\");
strcat(directory_file, LOG_NAME);
if ((log = fopen(directory_file, "w")) == NULL)
{
printf("Error");
}
My program worked until i tried to write into a file in order to create a log file. This means that the path is correct without doubt.
Can anyone tell me the problem here?
You have several issues in your code:
For one, fopen(path, "2"); is not valid.
The mode argument needs to include one of a, r, and w and can optionally include b or +.
As another thing, directory_path[strlen(directory_path) - 1] = 0; may truncate the end of your path (if it's over PATH_LEN characters long).
There also may be a possible issue with buffer overflow due to the fact that you copy a string to a buffer of the same size and then concatenate two other strings to it. Therefore, you should change this line:
char directory_file[PATH_LEN] = { 0 };
to this:
char directory_file[PATH_LEN+sizeof(LOG_NAME)+1] = { 0 };
To debug this issue, you should print the string entered and ask for confirmation before using it (wrap this in #ifdef DEBUG).

How to get /etc/ directory

I have function:
gint isfileexists(gchar *filename)
{
struct stat buffer;
gint i = stat(filename, &buffer);
if (i == 0) {
return 1;
}
return 0;
}
and if I call them:
isfileexists("/etc/myfile")
it search "myfile" in "/home/user/etc/myfile". How to do this well?
It should only look for /home/USER/etc/myfile if:
you leave off the leading / when calling isfileexists; and
that directory /home/USER is your current working directory.
In other words, if the argument is a relative path name.
Since you have the leading /, it will be an absolute path name and should access /etc/myfile.
If I've misunderstood and you actually want the one in your home directory, you can use getenv("HOME") to get your home directory and then append /etc/myfile with strcat. That will also work regardless of your current working directory.

Nagios plugin (written in C) unable to open file

I have a plugin written in c that will parse a .log file and determine the page hit count:
_xLogFileName = "./loging.log";
/* File operation starts here */
_xFile = fopen ( _xLogFileName, "r" );
if ( _xFile != NULL )
{
//read a line upto the end of the file
while ( fgets ( _xFileLine , sizeof _xFileLine, _xFile ) != NULL )
{
// #_xTiemInStr --> cur date in YYYY-MM-DD format to identify todays log
if(strstr(_xFileLine, _xTiemInStr) != NULL) {
if(strstr(_xFileLine, _xLoginHitString) != NULL) {
_xLoginPageCounter = _xLoginPageCounter + 1;
}
}
}
printf("Usage:Total Login Page Hit :%d\n",_xLoginPageCounter );
fclose ( _xFile );
return 0;
}
else
{
printf("error\n");
perror ( _xLogFileName );
return 3;
}
return 0;
Now I placed the a.out file in /usr/lib/nagios/plugin folder and placed the "loging.log" file in the same folder- for both chmod 777 done. I can run the plugin from command line but when I integrate the same with nagios then it is giving unknown status and printing the "error" from else part-- can anyone please help
2nd part
In addition I added the following code to determine from where the nagios is running?
char cwd[1024];
_xLogFileName1 = "loging.log";
if (getcwd(cwd, sizeof(cwd)) != NULL)
_xLogFileName = strcat( cwd,_xLogFileName1);
printf("FileName : %s\n", _xLogFileName);
and it is printing /loging.log in status information?
So where I have to actually place the file, my nagios is running from /etc/nagios3 and I placed the loging.log file there also but still it is not working.
UPDATE: Now it is working, as I print the pwd by the c program and find that it is running from my root (/) dir , so I placed the loging.log file there and now it is working fine.
You should be passing the full path to the file and storing that in '_xLogFileName1', and not just the file name alone. Strongly recommend that you do not copy files into the root directory.
Knowing web logs, it is very likely that the date string you're looking for is at the front of the line. So I'd recommend using 'strnstr' instead of 'strstr'. It would greatly improve your search speed.

a recursive function to manipulate a given path

I am working on modifying the didactic OS xv6 (written in c) to support symbolic links (AKA shortcuts).
A symbolic link is a file of type T_SYM that contains a path to it's destination.
For doing that, i wrote a recursive function that gets a path and a buffer and fills the buffer with the "real" path (i.e. if the path contains a link, it should be replaced by the real path, and a link can occur at any level in the path).
Basically, if i have a path a/b/c/d, and a link from f to a/b, the following operations should be equivalent:
cd a/b/c/d
cd f/c/d
Now, the code is written, but the problem that i try to solve is the problem of starting the path with "/" (meaning that the path is absolute and not relative).
Right now, if i run it with a path named /dir1 it treats it like dir1 (relative instead of absolute).
This is the main function, it calls the recursive function.
pathname is the given path, buf will contain the real path.
int readlink(char *pathname, char *buf, size_t bufsize){
char name[DIRSIZ];
char realpathname[100];
memset(realpathname,0,100);
realpathname[0] = '/';
if(get_real_path(pathname, name, realpathname, 0, 0)){
memmove(buf, realpathname, strlen(realpathname));
return strlen(realpathname);
}
return -1;
}
This is the recursive part.
the function returns an inode structure (which represents a file or directory in the system). it builds the real path inside realpath.
ilock an iunlock are being used to use the inode safely.
struct inode* get_real_path(char *path, char *name, char* realpath, int position){
struct inode *ip, *next;
char buf[100];
char newpath[100];
if(*path == '/')
ip = iget(ROOTDEV, ROOTINO);// ip gets the root directory
else
ip = idup(proc->cwd); // ip gets the current working directory
while((path = skipelem(path, name)) != 0){name will get the next directory in the path, path will get the rest of the directories
ilock(ip);
if(ip->type != T_DIR){//if ip is a directory
realpath[position-1] = '\0';
iunlockput(ip);
return 0;
}
if((next = dirlookup(ip, name, 0)) == 0){//next will get the inode of the next directory
realpath[position-1] = '\0';
iunlockput(ip);
return 0;
}
iunlock(ip);
ilock(next);
if (next->type == T_SYM){ //if next is a symbolic link
readi(next, buf, 0, next->size); //buf contains the path inside the symbolic link (which is a path)
buf[next->size] = 0;
iunlockput(next);
next = get_real_path(buf, name, newpath, 0);//call it recursively (might still be a symbolic link)
if(next == 0){
realpath[position-1] = '\0';
iput(ip);
return 0;
}
name = newpath;
position = 0;
}
else
iunlock(next);
memmove(realpath + position, name, strlen(name));
position += strlen(name);
realpath[position++]='/';
realpath[position] = '\0';
iput(ip);
ip = next;
}
realpath[position-1] = '\0';
return ip;
}
I have tried many ways to do it right but with no success. If anyone sees the problem, i'd be happy to hear the solution.
Thanks,
Eyal
I think it's clear that after running get_real_path(pathname, name, realpathname, 0, 0) the realpathname cannot possibly start with a slash.
Provided the function executes successfully, the memmove(realpath + position, name, strlen(name)) ensures that realpath starts with name, as the position variable always contains zero at the first invocation of memmove.
I'd suggest something like
if(*path == '/') {
ip = iget(ROOTDEV, ROOTINO); // ip gets the root
realpath[position++] = '/';
} else
ip = idup(proc->cwd); // ip gets the current working directory
P.S. I'm not sure why you put a slash into the realpathname before executing the get_real_path, since at this point you don't really know whether the path provided is an absolute one.
Ok, found the problem...
The problem was deeper than what i thought...
Somehow the realpath was changed sometimes with no visible reason... but the reason was the line:
name = newpath;
the solution was to change that line to
strcpy(name,newpath);
the previous line made a binding between the name and the realpath... which can be ok if we were not dealing with softlinks. When dereferencing a subpath, this binding ruined everything.
Thanks for the attempts

Resources