How to create a virtual absolute path
Fri, Jan 19 2024 18:15:56 KSTThis function creates a virtual absolute path.
One thing to consider is that the path does not exceed PATH_MAX
.
If you input a relative path, it will be combined with the result of
the getcwd()
function.
..
is resolved.- Duplicate slashes are converted into one.
- The trailing slash is removed.
/*
To use nullptr , use the -std=c23 option.
cc -std=c23 vpath.c -o vpath
*/
#include <stdio.h>
#include "c-str.h"
#include <stdlib.h>
#include "c-array.h"
#include <unistd.h>
#include <string.h>
#include <limits.h>
char* vpath (const char* path)
{
if (path == nullptr || path[0] == '\0')
return nullptr;
CArray* array = c_array_new (nullptr, false);
if (path[0] != '/')
{
char* cwd = getcwd (nullptr, 0);
char** strv = c_str_split (cwd, '/');
for (int i = 0; strv[i]; i++)
c_array_add (array, strv[i]);
free (strv);
free (cwd);
}
char** strv = c_str_split (path, '/');
for (int i = 0; strv[i]; i++)
{
if (strv[i][0] == '\0')
{
if (array->len == 0)
c_array_add (array, strv[i]);
else
free (strv[i]);
}
else if (c_str_equal (strv[i], "."))
{
free (strv[i]);
}
else if (c_str_equal (strv[i], ".."))
{
free (strv[i]);
if (array->len > 1)
{
free (array->data[array->len - 1]);
c_array_remove_index (array, array->len - 1);
}
}
else
{
c_array_add (array, strv[i]);
}
}
c_array_add (array, nullptr);
free (strv);
strv = (char**) c_array_free (array);
char* path2 = c_strv_join ((const char**) strv, "/");
c_strv_free (strv);
if (strlen (path2) > PATH_MAX)
{
free (path2);
return nullptr;
}
return path2;
}
int main (int argc, char** argv)
{
if (argc != 2)
{
printf ("Usage: vpath <path>\n");
return 1;
}
printf ("input: %s\n", argv[1]);
char* path = vpath (argv[1]);
if (path)
{
printf ("output: %s\n", path);
free (path);
}
return 0;
}