getcwd сократить домашнюю директорию
Здравствуйте! Есть код
char cwd[1024];
getcwd(cwd, sizeof(cwd));
При вызове возвращает: /home/example/exampledir/
. Как заменить /home/example
на ~/
, если это домашняя директория юзера.
Здравствуйте! Есть код
char cwd[1024];
getcwd(cwd, sizeof(cwd));
При вызове возвращает: /home/example/exampledir/
. Как заменить /home/example
на ~/
, если это домашняя директория юзера.
Чуть развёрнутей:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *
cwd2home( char * path, size_t path_length )
{
char cwd[PATH_MAX];
char * home = getenv( "HOME" );
size_t home_length = strlen( home );
getcwd( cwd, sizeof(cwd) );
if( !strncmp( cwd, home, home_length ) )
{
strncpy( path, "~", path_length );
strncat( path, cwd + home_length, path_length - sizeof("~") );
}
else
{
strncpy( path, cwd, path_length );
}
path[path_length-1] = 0;
return path;
}
int
main()
{
char path[PATH_MAX];
printf( "%s\n", cwd2home(path, sizeof(path)) );
return 0;
}
На всякий случай, (мне кажется так будет поаккуратней с проверками и пожалуй как-то даже соответствует man getcwd
) я бы написал (название для функции лучше сами придумайте):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
char *
get2cwd (char *buf, size_t size)
{
if (buf = getcwd(buf, size)) {
struct passwd *p = getpwuid(getuid());
char *home;
if (p && (home = p->pw_dir)) {
int home_len = strlen(home), cwdlen = strlen(buf);
if (home_len < cwdlen && buf[home_len] == '/' &&
strncmp(buf, home, home_len) == 0) {
memmove(buf + 1, buf + home_len, cwdlen - home_len + 1);
*buf = '~';
}
} else
perror(p ? "no home" : "getpwuid(getuid())");
}
return buf;
}
Update
Про get_current_dir_name()
, слова в manpage
If the environment variable PWD is set, and its value is correct, then that value will be returned
и сомнениях @klopp (см. комментарии), можно ли ее использовать.
Как и обещал вчера, посмотрел код из eglibc-2.11.1/io/getdirname.c
/* Return a malloc'd string containing the current directory name.
If the environment variable `PWD' is set, and its value is correct,
that value is used. */
char *
get_current_dir_name (void)
{
char *pwd;
struct stat64 dotstat, pwdstat;
pwd = getenv ("PWD");
if (pwd != NULL
&& stat64 (".", &dotstat) == 0
&& stat64 (pwd, &pwdstat) == 0
&& pwdstat.st_dev == dotstat.st_dev
&& pwdstat.st_ino == dotstat.st_ino)
/* The PWD value is correct. Use it. */
return __strdup (pwd);
return __getcwd ((char *) NULL, 0);
}
IMHO все очевидно. Если "." и getenv("PWD") это одно и то же оглавление, то берем ранее уже кем-то (ну, естественно, шеллом) добытый путь, иначе вызываем дорогостоящий системный вызов -- getcwd.
(Если всем понятно, почему дорогостоящий -- замечательно, если нет -- спрашивайте (и сами тоже ищите, а лучше вычисляйте правильный ответ) и обсуждайте здесь, а можно ли это ускорить.
А то, я смотрю что-то совсем тут начинающие хакеры исчезли. Впечатление, что уже ничто никому не интересно).