Как получить путь с учетом регистра в 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;

}
Другие вопросы по тегам