I would like to know how an absolute path of a symbolic link can be converted to relative based on a given directory (that includes the linked file) in c language on linux (Ubuntu) OS.
I thought searching for the sub-string of the relative path, but what if it already exists higher in the folder's hierarchy?
Here is a more specific description of what I want to do: Relative path:
folder/folder1/folder2
Absolut path:
/home/giorgos/Desktop/folder/folder1/folder2/a.pdf
changed to
/home/giorgos/Desktop/myfolder/folder1/folder2/a.pdf
Obviously I cant' simply search for and replace "folder/", consider this case:
/home/giorgos/Desktop/folder/folder/folder/folder1/folder2/a.pdf
It can be searched both forwards and backwards and if replaced it still gives a wrong output Only if I knew the relative path I could search the absolute backwards and replace it, then the output would be correct:
/home/giorgos/Desktop/folder/myfolder/folder/folder1/folder2/a.pdf
I'd be seriously tempted to make the decision, if I were writing this tool, that absolute symbolic links should have the same value when moved somewhere else in the filesystem -- the user wanted a very specific file. And, relative symbolic links should have the same value when moved somewhere else in the filesystem -- the user wanted the links to work regardless of where the directory tree was rooted.
But if the two types of links were intermixed, then you'd have some more work to do -- which is where I assume you are now. (Unix programs are often not that forgiving about guessing a user's intent; if you just readlink(2)
and symlink(2)
exactly what the filesystem says, your program will never be surprising.)
rsync(1)
might have some source code you can use -- or at least learn from. The --safe-links
command line option causes rsync
to ignore absolute symbolic links and relative symbolic links that point outside the trees it was instructed to copy. This isn't canonicalizing paths to relative as you wish but it may provide sufficient code for discovering which links point outside the directory tree in question.
Slightly related; the Linux-specific symlinkat(2)
system call may make it easier for you to create your symbolic links. (The family of ...at()
system calls are something like providing a process with multiple "current working directories" without forcing you to make all the fchdir(2)
calls yourself.)
Converting a path to relative is a matter of first seeing how many base atoms are shared between the two paths, and then inserting ../ to navigate backwards up the tree before navigating down the correct branch. IE going from: /foo/bar/some/path
to /foo/other/path
you'll first see that they share /foo, to navigate upwards to that point you need 3 ../, turning the relative path into /foo/../../../other/path
. There's a boost::filesystem example for C++ here , save for the C++ & boost::filesystem the same can be done in C.
Well at first I didn't consider the following as important information, but with the help of a function I found out the absolute path to the original and copy directories.
This way I could finally get the original's folder "relative path" (path starting from original folder) change the root node of the dir's tree name to the copied folder's then get the absolute path of the copied folder and append the copied "relative path" and that was it!
realpath(directory,absolutePath);
This is what my code looks like :
readlink(A[i].str, oldLink, NAMESIZE);//A is the struct I keep the paths to directory entries
k=0;
j=strlen(absolutPath);
while(oldLink[j]!='\0')
{
fixLink[k]=oldLink[j];
j++;
k++;
}
strcpy(tmpLink,newAbsolutPath);
strcat(tmpLink,fixLink);
symlink (tmpLink,tmpPath);//tmpPath is the name of the link, tmp link is the absolute path to the actual file
//tmpPath is built almost the same way
So far it runs without any bugs
来源:https://stackoverflow.com/questions/9663845/how-to-convert-absolute-path-to-relative-in-c-linux