sprintf add special character in C - c

can anyone help me. I'm trying to create a folder, but when I use sprintf, it concatenates at the end special characters like OUUUU, how can I fix it?
there is an image (link below) where you can see the directory variable that has "/home/mia" and the buffer has "mkdir/home/miaOUUUU"
Any suggestions?
i'm using codeblocks in debian...
https://drive.google.com/file/d/1q3KKBbyDjA8_dfwKT54_OT_5QeREIz7k/view?usp=sharing

You should post the code in the body of the question, with copy+paste from your IDE and one extra indentation level (select the code and type Alt-K for that), not as a link to a bitmap, it is very rude.
directorio is not null terminated. You must declare it with one extra element as char directorio[i + 1]; and make sure to initialize directorio[i] to '\0'.
The memset is useless since you overwrite the whole buffer in the subsequent for loop. Do this instead:
char directorio[i + 1];
memcpy(directorio, path, i);
directorio[i] = '\0';
DIRP *dirp = opendir(directorio);
if (dirp == NULL) {
...
} else {
// do not forget to close the directory
closedir(dirp);
}
Also note that you should create directories from the root directory to the final path, and you should handle the spurious case of an existing file with the same name as one of the directories along the path.

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

LINUX C how to convert two full path's to a relative path (updated) [duplicate]

Given two absolute paths, e.g.
/a/path/to/a
/a/path/to/somewhere/else
How can I get a relative path from one to the other, ../a?
In a sense, the opposite of what realpath does.
Find the longest common path (in this case, /a/path/to) and delete it from both absolute paths. That would give:
/a
/somewhere/else
Now, replace each path component in the starting path with ../ and prepend the result to the destination path. If you want to go from directory else to directory a, that would give you:
../../a
If you want to go the other way, you'd instead have:
../somewhere/else
I answered a similar question here: Resolving a relative path without referencing the current directory on Windows.
There is no standard function for this. There is a function in vi-like-emacs for this purpose. A quick check of apropos relative shows me few other programs which likely implement this: revpath for example).
It could be done as a string-manipulation (no need to compute working directories):
start by finding the longest common prefix which ends with a path-separator.
if there is no common prefix, you are done
strip the common prefix from (a copy of...) the current and target strings
replace each directory-name in the current string with ".."
add that (with a path-separator) in front of the target string
return that combined string
The "done" in the second step presumes that you want to use a relative path to shorten the result. On the other hand, you might want to use a relative pathname regardless of the length. In that case, just skip the step (the result will be longer, but relative).
Build a tree with the first absolute path, then add the second path to that tree, and then walk from one leaf to the other: a step from one node to its parent is translated to a "../" sequence, and a step from a node to one of its children is translated to the name of that children. Notice that there might be more than one solution. For example:
1) /a/path/to/a
And
2) /a/path/to/a/new/one
The obvious path from (1) to (2) is new/one but ../../../a/path/to/a/new/one is also valid. When you write the algorithm to do the walking in your tree you have to be aware of this
Using cwalk you can use cwk_path_get_relative, which even works cross-platform:
#include <cwalk.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char buffer[FILENAME_MAX];
cwk_path_get_relative("/hello/there/", "/hello/world", buffer, sizeof(buffer));
printf("The relative path is: %s", buffer);
return EXIT_SUCCESS;
}
Output:
The relative path is: ../world
This is implemented in the "ln" command, part of the GNU Coreutils package (for ln -r). Obviously there are many ways to go about this, and one could even derive some benefit from coming up with a solution oneself, without looking at existing code. Personally I find the code in Coreutils to be rather instructive.
If I had to convert absolute paths to a relative path in a C project, I would just copy "relpath.c" from Coreutils. It has a few dependencies to other utility functions in the package, these would need to be brought in in some form as well. Here is the main "relpath()" function. Note that it works on canonicalized pathnames, for example it doesn't like for paths to contain stuff like "//" or "/.". Basically it finds the common prefix of the two paths, then it treats the four cases which arise depending on whether the remaining part of each path is empty or not.
/* Output the relative representation if possible.
If BUF is non-NULL, write to that buffer rather than to stdout. */
bool
relpath (const char *can_fname, const char *can_reldir, char *buf, size_t len)
{
bool buf_err = false;
/* Skip the prefix common to --relative-to and path. */
int common_index = path_common_prefix (can_reldir, can_fname);
if (!common_index)
return false;
const char *relto_suffix = can_reldir + common_index;
const char *fname_suffix = can_fname + common_index;
/* Skip over extraneous '/'. */
if (*relto_suffix == '/')
relto_suffix++;
if (*fname_suffix == '/')
fname_suffix++;
/* Replace remaining components of --relative-to with '..', to get
to a common directory. Then output the remainder of fname. */
if (*relto_suffix)
{
buf_err |= buffer_or_output ("..", &buf, &len);
for (; *relto_suffix; ++relto_suffix)
{
if (*relto_suffix == '/')
buf_err |= buffer_or_output ("/..", &buf, &len);
}
if (*fname_suffix)
{
buf_err |= buffer_or_output ("/", &buf, &len);
buf_err |= buffer_or_output (fname_suffix, &buf, &len);
}
}
else
{
buf_err |= buffer_or_output (*fname_suffix ? fname_suffix : ".",
&buf, &len);
}
if (buf_err)
error (0, ENAMETOOLONG, "%s", _("generating relative path"));
return !buf_err;
}
You can view the rest of "relpath.c" here. There is a higher-level wrapper function in "ln.c" which canonicalizes its path name arguments before calling relpath, it is named convert_abs_rel(). That's probably what you want to be calling most of the time.

Regarding FOPEN in C

I am having a problem regarding FOPEN in C.
I have this code which reads a particular file from a directory
FILE *ifp ;
char directoryname[50];
char result[100];
char *rpath = "/home/kamal/samples/pipe26/divpipe0.f00001";
char *mode = "r";
ifp = fopen("director.in",mode); %director file contains path of directory
while (fscanf(ifp, "%s", directoname) != EOF)
{
strcpy(result,directoname); /* Path of diretory /home/kamal/samples/pipe26 */
strcat(result,"/"); /* front slash for path */
strcat(result,name); /* name of the file divpipe0.f00001*/
}
Till this point my code works perfectly creating a string which looks " /home/kamal/samples/pipe26/divpipe0.f00001 ".
The problem arises when I try to use the 'result' to open a file, It gives me error. Instead if I use 'rpath' it works fine even though both strings contain same information.
if (!(fp=fopen(rpath,"rb"))) /* This one works fine */
{
printf(fopen failure2!\n");
return;
}
if (!(fp=fopen(result,"rb"))) /* This does not work */
{
printf(fopen failure2!\n");
return;
}
Could some one please tell why I am getting this error ?
I think you mean char result[100];; i.e. without the asterisk. (Ditto for directoryname.)
You're currently stack-allocating an array of 100 pointers. This will not end well.
Note that rpath and mode point to read-only memory. Really you should use const char* for those two literals.
The error is the array 'char* result[100]', here you are allocating an array of 100 pointers to strings, not 100 bytes / characters, which was your intent.

How to find relative path given two absolute paths?

Given two absolute paths, e.g.
/a/path/to/a
/a/path/to/somewhere/else
How can I get a relative path from one to the other, ../a?
In a sense, the opposite of what realpath does.
Find the longest common path (in this case, /a/path/to) and delete it from both absolute paths. That would give:
/a
/somewhere/else
Now, replace each path component in the starting path with ../ and prepend the result to the destination path. If you want to go from directory else to directory a, that would give you:
../../a
If you want to go the other way, you'd instead have:
../somewhere/else
I answered a similar question here: Resolving a relative path without referencing the current directory on Windows.
There is no standard function for this. There is a function in vi-like-emacs for this purpose. A quick check of apropos relative shows me few other programs which likely implement this: revpath for example).
It could be done as a string-manipulation (no need to compute working directories):
start by finding the longest common prefix which ends with a path-separator.
if there is no common prefix, you are done
strip the common prefix from (a copy of...) the current and target strings
replace each directory-name in the current string with ".."
add that (with a path-separator) in front of the target string
return that combined string
The "done" in the second step presumes that you want to use a relative path to shorten the result. On the other hand, you might want to use a relative pathname regardless of the length. In that case, just skip the step (the result will be longer, but relative).
Build a tree with the first absolute path, then add the second path to that tree, and then walk from one leaf to the other: a step from one node to its parent is translated to a "../" sequence, and a step from a node to one of its children is translated to the name of that children. Notice that there might be more than one solution. For example:
1) /a/path/to/a
And
2) /a/path/to/a/new/one
The obvious path from (1) to (2) is new/one but ../../../a/path/to/a/new/one is also valid. When you write the algorithm to do the walking in your tree you have to be aware of this
Using cwalk you can use cwk_path_get_relative, which even works cross-platform:
#include <cwalk.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char buffer[FILENAME_MAX];
cwk_path_get_relative("/hello/there/", "/hello/world", buffer, sizeof(buffer));
printf("The relative path is: %s", buffer);
return EXIT_SUCCESS;
}
Output:
The relative path is: ../world
This is implemented in the "ln" command, part of the GNU Coreutils package (for ln -r). Obviously there are many ways to go about this, and one could even derive some benefit from coming up with a solution oneself, without looking at existing code. Personally I find the code in Coreutils to be rather instructive.
If I had to convert absolute paths to a relative path in a C project, I would just copy "relpath.c" from Coreutils. It has a few dependencies to other utility functions in the package, these would need to be brought in in some form as well. Here is the main "relpath()" function. Note that it works on canonicalized pathnames, for example it doesn't like for paths to contain stuff like "//" or "/.". Basically it finds the common prefix of the two paths, then it treats the four cases which arise depending on whether the remaining part of each path is empty or not.
/* Output the relative representation if possible.
If BUF is non-NULL, write to that buffer rather than to stdout. */
bool
relpath (const char *can_fname, const char *can_reldir, char *buf, size_t len)
{
bool buf_err = false;
/* Skip the prefix common to --relative-to and path. */
int common_index = path_common_prefix (can_reldir, can_fname);
if (!common_index)
return false;
const char *relto_suffix = can_reldir + common_index;
const char *fname_suffix = can_fname + common_index;
/* Skip over extraneous '/'. */
if (*relto_suffix == '/')
relto_suffix++;
if (*fname_suffix == '/')
fname_suffix++;
/* Replace remaining components of --relative-to with '..', to get
to a common directory. Then output the remainder of fname. */
if (*relto_suffix)
{
buf_err |= buffer_or_output ("..", &buf, &len);
for (; *relto_suffix; ++relto_suffix)
{
if (*relto_suffix == '/')
buf_err |= buffer_or_output ("/..", &buf, &len);
}
if (*fname_suffix)
{
buf_err |= buffer_or_output ("/", &buf, &len);
buf_err |= buffer_or_output (fname_suffix, &buf, &len);
}
}
else
{
buf_err |= buffer_or_output (*fname_suffix ? fname_suffix : ".",
&buf, &len);
}
if (buf_err)
error (0, ENAMETOOLONG, "%s", _("generating relative path"));
return !buf_err;
}
You can view the rest of "relpath.c" here. There is a higher-level wrapper function in "ln.c" which canonicalizes its path name arguments before calling relpath, it is named convert_abs_rel(). That's probably what you want to be calling most of the time.

Resources