Итак, в основном, что вам действительно нужно, так это получить файловый дескриптор и, по сути, снова открыть тот же файл, чтобы получить отдельную позицию, совместное использование, режим и т. д. И вы хотите сделать это в Windows (где «файловый дескриптор " в основном является посторонним объектом, а не чем-то, что используется напрямую ОС или библиотекой времени выполнения вообще.
Удивительно, но есть способ сделать это, по крайней мере, с помощью MS VC++. Все, кроме двух шагов, используют только Win32 API, поэтому перенос на другие компиляторы/библиотеки должен быть достаточно разумным (я думаю, что большинство версий этих двух функций). Они предназначены для преобразования дескриптора файла в стиле Unix в собственный дескриптор файла Win32 и преобразования собственного дескриптора файла Win32 обратно в дескриптор файла в стиле Unix.
- Преобразование дескриптора файла в собственный дескриптор файла с помощью _get_osfhandle()
- Получите имя файла с помощью GetFileInformationByHandleEx(FILE_NAME_INFO)1
- Используйте CreateFile, чтобы открыть новый дескриптор этого файла.
- Создайте файловый дескриптор для этого дескриптора с помощью _open_osfhandle().
Вуаля, у нас есть новый файловый дескриптор, ссылающийся на тот же файл, но с собственными разрешениями, положением и т. д.
Ближе к концу вашего вопроса вы говорите, что вам также нужны «разрешения», но это, похоже, не имеет никакого реального смысла — разрешения прикрепляются к самому файлу, а не к тому, как файл открывается, поэтому открытие или повторное открытие файла не влияет на права доступа к файлу. Если вы действительно хотите знать, вы можете получить его с помощью GetFileInformationByHandle, но имейте в виду, что права доступа к файлам в Windows немного отличаются от (традиционных) прав доступа к файлам в Unix. Unix имеет разрешения владельца/группы/мира для всех файлов, и в большинстве систем также есть ACL (хотя есть больше различий в том, как они работают). Windows либо вообще не имеет разрешений (например, файлы в FAT или FAT32), либо использует ACL (например, файлы в NTFS), но ничего, что действительно эквивалентно традиционным разрешениям владельца/группы/мира, к которым привыкло большинство людей в Unix.
Возможно, вы используете «разрешения», чтобы указать, был ли файл открыт для чтения, записи или того и другого. Получение этого значительно уродливее любого из предыдущих. Проблема в том, что большая часть этого находится в библиотеке, а не в Win32, поэтому, вероятно, нет способа сделать это, который был бы даже близок к переносимости между компиляторами. С MS VC++ 9.0 SP1 (не гарантируется для любого другого компилятора) вы можете сделать это:
#include <stdio.h>
int get_perms(int fd) {
int i;
FILE * base = __iob_func();
for (i=0; i<_IOB_ENTRIES; i++)
if (base[i]._file == fd)
return base[i]._flag; // we've found our file
return 0; // file wasn't found.
}
Поскольку для этого потребовалось немного спелеологии, я написал быстрый тест, чтобы убедиться, что он действительно работает:
#ifdef TEST
#include <io.h>
void show_perms(int perms, char const *caption) {
printf("File opened for %s\n", caption);
printf("Read permission = %d\n", (perms & _IOREAD)!=0);
printf("Write permission = %d\n", (perms & _IOWRT)!=0);
}
int main(int argc, char **argv) {
FILE *file1, *file2;
int perms1, perms2;
file1=fopen(argv[1], "w");
perms1 = get_perms(_fileno(file1));
fclose(file1);
file2=fopen(argv[1], "r");
perms2 = get_perms(_fileno(file2));
fclose(file2);
show_perms(perms1, "writing");
show_perms(perms2, "reading");
return 0;
}
#endif
И результаты, кажется, указывают на успех:
File opened for writing
Read permission = 0
Write permission = 1
File opened for reading
Read permission = 1
Write permission = 0
Затем вы можете проверить возвращенный флаг на соответствие _IOREAD, _IOWRT и _IORW, которые определены в stdio.h. Несмотря на мои предыдущие предупреждения, я, вероятно, должен указать, что я подозреваю (хотя я, конечно, не могу гарантировать), что эта часть библиотеки довольно стабильна, поэтому реальные шансы на серьезные изменения, вероятно, довольно минимальны.
С другой стороны, однако, совсем нет никаких шансов, что он будет работать с какой-либо другой библиотекой. Он может (но точно не гарантируется) работать с другими компиляторами, использующими библиотеку MS, такими как Intel, MinGW или Comeau, использующими MS VC++ в качестве серверной части. Из них я бы сказал, что с наибольшей вероятностью будет работать Comeau, а с наименьшей - MinGW (но это только предположение; есть большая вероятность, что это не сработает ни с одним из них).
- Требуется распространяемая библиотека Win32 FileID API а>
person
Jerry Coffin
schedule
27.10.2009