Как получить путь с учетом регистра в Linux без итерации каталога?
Имеется смонтированная файловая система cifs /network/cifs
который нечувствителен к регистру, как получить путь с учетом регистра с помощью C?
Например, у фс есть файл /network/cfis/Adena/t.txt
, Дано /network/cfis/AdEnA/T.txt
(который правильно разрешает), я хочу /network/cfis/Adena/t.txt
,
Я знаю, что один из способов сделать это - рекурсивно выполнять итерацию по пути, сопоставлять их со всеми строчными буквами и получать фактический регистр, возвращаемый итерацией каталога. Однако это включает в себя множество системных вызовов, которые я бы предпочел не делать.
Изменение параметров монтирования не является решением.
Если это невозможно, возможно ли определить, находится ли путь в файловой системе без учета регистра? Таким образом, я могу избежать рекурсивной итерации каталогов, если это не требуется.
4 ответа
Этот вопрос только что возник вчера вечером в IRC; мой ответ был, что вы должны повторить, и причина в том, что getcwd
(который может быть реализован, просто посмотрев на /proc/N/
файлы в Linux) не является надежным для определения канонического имени. Модуль ядра Linux CIFS будет подделывать inode на лету с тем корпусом, который вы просили:
ls -dli /mnt/foo /mnt/foO /mnt/fOo /mnt/FOo /mnt/FOO
может показать очень разные значения, и, как таковой, /proc/self/cwd
будет отражать один из этих inode, не обязательно тот, который имеет каноническое именование.
Для чего это стоит, вот способ, который работает на OSX (но, видимо, не Linux):
#include <stdlib.h>
char case_sensitive_path[1024];
realpath("/network/cfis/AdEnA/T.txt", case_sensitive_path);
// case_sensitive_path is now "/network/cfis/Adena/t.txt"
Возможное решение может состоять в том, чтобы открыть файл для чтения, получить дескриптор файла, например 23, а затем прочитать ссылку на псевдофайл /proc/self/fd/23
(но, возможно, этот трюк не сработает, я не пробовал)
#include <stdlib.h>
#include <stdio.h> /* defines FILENAME_MAX */
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
int main(void)
{
char buffer[FILENAME_MAX];
chdir("/network/cfis/AdEnA");
if (NULL == GetCurrentDir(buffer, FILENAME_MAX))
perror("getcwd error");
printf("The current directory is %s.\n", buffer);
return 0;
}