Ответ 1
Итак, в основном, вам действительно нужен файловый дескриптор и в основном открыть тот же файл заново, чтобы получить отдельную позицию, общий доступ, режим и т.д. И вы хотите сделать это на Windows (где "файловый дескриптор" - это в основном посторонний объект, а не то, что непосредственно используется ОС или библиотекой времени выполнения.
Удивительно, но есть способ сделать это, по крайней мере, с MS VС++. Все, кроме двух этапов, используют только API Win32, поэтому перенос на другие компиляторы/библиотеки должен быть достаточно разумным (я думаю, что большинство версий версий этих двух функций). Они предназначены для преобразования дескриптора файла стиля Unix в собственный дескриптор файла Win32 и преобразования собственного дескриптора файла Win32 обратно в дескриптор файла в стиле Unix.
- Преобразовать дескриптор файла в собственный дескриптор файла с помощью _get_osfhandle()
- Получить имя файла с GetFileInformationByHandleEx (FILE_NAME_INFO) 1
- Используйте CreateFile, чтобы открыть новый дескриптор этого файла
- Создайте дескриптор файла для этого дескриптора с помощью _open_osfhandle()
Et voilà, у нас есть новый файловый дескриптор, относящийся к тому же файлу, но с его собственными разрешениями, позицией и т.д.
В конце вашего вопроса вы делаете это так, как будто вы также нуждаетесь в "разрешениях", но это, похоже, не имеет никакого реального смысла - разрешения прикрепляются к самому файлу, а не к тому, как файл открывается, поэтому открытие или повторное открытие файла не влияет на права доступа к файлу. Если вы действительно хотите знать это, вы можете получить его с помощью GetFileInformationByHandle, но имейте в виду, что права доступа к файлам в Windows немного отличаются от (традиционных) разрешений файлов в Unix. У Unix есть права владельца/группы/мира для всех файлов, и большинство систем также имеют списки ACL (хотя есть больше различий в том, как они работают). Windows либо не имеет прав вообще (например, файлы на FAT или FAT32), либо использует ACL (например, файлы в NTFS), но ничего, что действительно эквивалентно традиционным правам владельца/группы/мира, к которым большинство людей привыкли в Unix.
Возможно, вы используете "разрешения", чтобы узнать, открыт ли файл для чтения, записи или того и другого. Получение этого значительно уродливее, чем любое из предыдущих. Проблема в том, что большинство из них находится в библиотеке, а не в Win32, поэтому, вероятно, нет способа сделать это, что будет даже близко к переносимым между компиляторами. С MS VС++ 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.
}
Так как это касалось некоторых spelunking, я написал быстрый тест, чтобы убедиться, что он может действительно работать:
#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 VС++ в качестве своего исходного кода. Из них я бы сказал, что наиболее вероятно, что это будет "Комо", и наименее вероятный MinGW (но это только предположение, там хороший шанс, что он не сработает ни с одним из них).
- Требуется распространяемая Библиотека API Win32 FileID