Здравствуйте, EreTIk, Вы писали:
ETI>Открыть объект файла, получить нормализованные пути (GetFinalPathNameByHandle(..., FILE_NAME_NORMALIZED) или FltGetFileNameInformationUnsafe(…, FLT_FILE_NAME_NORMALIZED, ...)) и сравнить их.
Задача определения эквиалентности путей имеет смысл даже если соответствующих файлов не существует. Однако предложенный тобой способ не сработает в данной ситуации.
Здравствуйте, Pzz, Вы писали:
Pzz>Задача определения эквиалентности путей имеет смысл даже если соответствующих файлов не существует. Однако предложенный тобой способ не сработает в данной ситуации.
Каков вопрос (насколько он полно задан) — таков ответ.
В более общем виде понятно, что будет миллион тонкостей:
каждая директория может быть точкой монтирования другого тома (что может давать эквивалентные DOS-пути, но при этом разные NT-пути)
каждая NTFS-директория на современной 10-ке может оказаться case sensitivity
у SymLink'ов, коим является "\SystemRoot", есть время жизни и возможность быть измененным
<…>
Здравствуйте, EreTIk, Вы писали:
ETI>Каков вопрос (насколько он полно задан) — таков ответ. ETI>В более общем виде понятно, что будет миллион тонкостей: ETI>
ETI> каждая директория может быть точкой монтирования другого тома (что может давать эквивалентные DOS-пути, но при этом разные NT-пути) ETI> каждая NTFS-директория на современной 10-ке может оказаться case sensitivity ETI> у SymLink'ов, коим является "\SystemRoot", есть время жизни и возможность быть измененным ETI> <…> ETI>
Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.
Здравствуйте, Pzz, Вы писали:
Pzz>Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.
Эквивалентность вопросов для меня совсем не очевидна.
В операционной системе именем на томе заведует драйвер файловой системы. Если файла нет, то (с учетом точек повторного разбора) у операционной системы нет возможности узнать на какой файловой системе расположен файл, следовательно, нет возможности нормализовать и сравнить имя.
Здравствуйте, EreTIk, Вы писали:
ETI>В операционной системе именем на томе заведует драйвер файловой системы. Если файла нет, то (с учетом точек повторного разбора) у операционной системы нет возможности узнать на какой файловой системе расположен файл, следовательно, нет возможности нормализовать и сравнить имя.
Ну нет, конечно. Если хотя бы у одного файла существует директория, в которой он должен быть расположен, то пути эквиавалентны, если у второго файла тоже существует директория, и эти директории совпадают.
Если же оба пути указывают на несуществующую директорию, то надо для обеих путей найти самую "внутреннюю" существующую директорию, убедиться в том, что это именно директория, а не регулярный файл, привести обе директории к каноническому виду, и интерпретировать остаток путей относительно этих директорий. Если в результате получатся одинаковые пути, то пути совпадают.
Здравствуйте, Pzz, Вы писали:
Pzz>Ну нет, конечно. Если хотя бы у одного файла существует директория, в которой он должен быть расположен, то пути эквиавалентны, если у второго файла тоже существует директория, и эти директории совпадают.
Как матчить сами имена файлов-то, откидывая директории? Например если в качестве имени файла в первом случае было указано длинное имя, а во втором — короткое (8.3, отличающееся от короткого) (файл существует, но недоступен вам для открытия и получения у него имени)?
Pzz>Если же оба пути указывают на несуществующую директорию, то надо для обеих путей найти самую "внутреннюю" существующую директорию, убедиться в том, что это именно директория, а не регулярный файл, привести обе директории к каноническому виду, и интерпретировать остаток путей относительно этих директорий. Если в результате получатся одинаковые пути, то пути совпадают.
Опять же непонятно как интерпретировать остаток, учитывая короткие-длинные имена, чувствительность к регистру?
Здравствуйте, EreTIk, Вы писали:
Pzz>>Ну нет, конечно. Если хотя бы у одного файла существует директория, в которой он должен быть расположен, то пути эквиавалентны, если у второго файла тоже существует директория, и эти директории совпадают.
ETI>Как матчить сами имена файлов-то, откидывая директории? Например если в качестве имени файла в первом случае было указано длинное имя, а во втором — короткое (8.3, отличающееся от короткого) (файл существует, но недоступен вам для открытия и получения у него имени)?
Буквально, с учетом чувствительности к регистру, характерной для той директории, где расположены файлы.
Pzz>>Если же оба пути указывают на несуществующую директорию, то надо для обеих путей найти самую "внутреннюю" существующую директорию, убедиться в том, что это именно директория, а не регулярный файл, привести обе директории к каноническому виду, и интерпретировать остаток путей относительно этих директорий. Если в результате получатся одинаковые пути, то пути совпадают.
ETI>Опять же непонятно как интерпретировать остаток, учитывая короткие-длинные имена, чувствительность к регистру?
Буквально, с учетом чувствительности к регистру, характерной для имеющейся существующей директории. Если они разные, ну, выбрать нечувствительное к регистру сравнение, как более характерное для вендов.
Этот способ не даст 100% точного ответа, но это будет гораздо более понятно пользователю, чем требование существование файла. Не надо забывать, что мы пишем программы для людей, а не для ЭВМ.
Здравствуйте, Pzz, Вы писали:
Pzz>Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.
Можно попросить у системы номер файла например
Здравствуйте, Pzz, Вы писали:
Pzz>Этот способ не даст 100% точного ответа, но это будет гораздо более понятно пользователю, чем требование существование файла. Не надо забывать, что мы пишем программы для людей, а не для ЭВМ.
Мы пишем программы для разных задач. И от условий задачи будет зависит правильный способ решения задачи. Возможно, к примеру, по условию задачи будет корректным в качестве результата сравнения возвращать три варианта: совпадают, не совпадают и невозможно достоверно сравнить. Но условий задачи, к сожалению, в исходном сообщении не было. А был приведен пример с существующим директориями C:\Windows\System32 и \SystemRoot.
_>Если номера совпали то директории одинаковые, но есть нюансы.
Такой идентификатор уникален только в рамках одного тома, необходимо уметь сравнивать тома. В MSDN, например, предлагают сравнивать серийные номера томов:
The identifier (low and high parts) and the volume serial number uniquely identify a file on a single computer. To determine whether two open handles represent the same file, combine the identifier and the volume serial number for each file and compare them.
Хотя мне кажется что присутствие в системе двух томов с одинаковыми серийниками возможно.
_>>Если номера совпали то директории одинаковые, но есть нюансы.
ETI>Такой идентификатор уникален только в рамках одного тома, необходимо уметь сравнивать тома. В MSDN, например, предлагают сравнивать серийные номера томов: ETI>
ETI>The identifier (low and high parts) and the volume serial number uniquely identify a file on a single computer. To determine whether two open handles represent the same file, combine the identifier and the volume serial number for each file and compare them.
ETI>Хотя мне кажется что присутствие в системе двух томов с одинаковыми серийниками возможно.
Не ну как вариант еще так можно
int GetFileGuid(GUID* result,LPCTSTR name) {
HANDLE h; FILE_OBJECTID_BUFFER id; DWORD rd; int res=1;
h=CreateFile(name,FILE_GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
if (DeviceIoControl(h, FSCTL_CREATE_OR_GET_OBJECT_ID,NULL, 0, &id, sizeof(id),&rd, NULL)) {
if (result) CopyMemory(result,&id.ObjectId, sizeof(GUID));
res=0;
}
CloseHandle(h);
return res;
}
Кроме того, что FAT (как и некоторые другие ФС) не поддерживает такие идентификаторы файлов, есть FSCTL_SET_OBJECT_ID. То есть данный идентификатор на NTFS может назначаться программно, значит двум файлам может быть назначен один и тот же идентификатор (специально или по ошибке).
Здравствуйте, EreTIk, Вы писали:
ETI>Кроме того, что FAT (как и некоторые другие ФС) не поддерживает такие идентификаторы файлов, есть FSCTL_SET_OBJECT_ID. То есть данный идентификатор на NTFS может назначаться программно, значит двум файлам может быть назначен один и тот же идентификатор (специально или по ошибке).
Некоторые другие файловые системы и symbolic link-и и mount-bind и собирать дирикторию из кучи других директорий умеют и что?
Даже в одной и той же винде одни приложения видят директорию c:\windows\system32\Microsoft а другие нет.
Если надо быстро и сердито все правила обрабатываем вручную. Если лень то GetFullPathName.
Для контроля методы с id и guid (но они могут надолго зависать на сетевых путях) и на крайняк можно в директории создать временный уникальный файл если хочеться удостовериться.
Как по мне я бы не заморачивался и считал бы все пути разными
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, Pzz, Вы писали:
Pzz>>Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система. _>Можно попросить у системы номер файла например _>
Pzz>Задача определения эквиалентности путей имеет смысл даже если соответствующих файлов не существует. Однако предложенный тобой способ не сработает в данной ситуации.
А если один файл существует, а второго нет, но если бы был, то был бы симлинком на первый?
S>Сделал с zwcreatefile + zwqueryobject(objectnameinformation). Вроде и так пойдет.
Походу всё таки не пойдет. Может вернуть короткий путь (с тильдой) хотя путь сам по себе не длинный.
Здравствуйте, EreTIk, Вы писали:
ETI>Каков вопрос (насколько он полно задан) — таков ответ.
Мне надо сравнивать путь до папок. FltGetFileNameInformation выглядит многообещающе, но где взять PFILE_OBJECT — не знаю.