Как сравнить пути ?
От: smbdnew  
Дата: 03.10.18 11:31
Оценка:
К примеру вот такие пути:
\Device\HardDiskVolume1\Windows\System32
\??\C:\Windows\System32
\SystemRoot\

Есть ли какой то способ ?
Re: Как сравнить пути ?
От: reversecode google
Дата: 03.10.18 11:39
Оценка: -2
что значит сравнить ?
стрцмп есть везде
Re: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 11:44
Оценка: +1
Здравствуйте, smbdnew, Вы писали:

S>К примеру вот такие пути:

S>\Device\HardDiskVolume1\Windows\System32
S>\??\C:\Windows\System32
S>\SystemRoot\

Открыть объект файла, получить нормализованные пути (GetFinalPathNameByHandle(..., FILE_NAME_NORMALIZED) или FltGetFileNameInformationUnsafe(…, FLT_FILE_NAME_NORMALIZED, ...)) и сравнить их.
Отредактировано 03.10.2018 11:56 EreTIk . Предыдущая версия . Еще …
Отредактировано 03.10.2018 11:47 EreTIk . Предыдущая версия .
Re[2]: Как сравнить пути ?
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.10.18 12:38
Оценка:
Здравствуйте, EreTIk, Вы писали:

ETI>Открыть объект файла, получить нормализованные пути (GetFinalPathNameByHandle(..., FILE_NAME_NORMALIZED) или FltGetFileNameInformationUnsafe(…, FLT_FILE_NAME_NORMALIZED, ...)) и сравнить их.


Задача определения эквиалентности путей имеет смысл даже если соответствующих файлов не существует. Однако предложенный тобой способ не сработает в данной ситуации.
Re[3]: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 12:55
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Задача определения эквиалентности путей имеет смысл даже если соответствующих файлов не существует. Однако предложенный тобой способ не сработает в данной ситуации.


Каков вопрос (насколько он полно задан) — таков ответ.
В более общем виде понятно, что будет миллион тонкостей:
Отредактировано 03.10.2018 12:57 EreTIk . Предыдущая версия .
Re[4]: Как сравнить пути ?
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.10.18 13:23
Оценка: -2
Здравствуйте, EreTIk, Вы писали:

ETI>Каков вопрос (насколько он полно задан) — таков ответ.

ETI>В более общем виде понятно, что будет миллион тонкостей:
ETI>
Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.
Re[5]: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 13:47
Оценка: +2
Здравствуйте, Pzz, Вы писали:

Pzz>Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.


Эквивалентность вопросов для меня совсем не очевидна.

В операционной системе именем на томе заведует драйвер файловой системы. Если файла нет, то (с учетом точек повторного разбора) у операционной системы нет возможности узнать на какой файловой системе расположен файл, следовательно, нет возможности нормализовать и сравнить имя.
Re[6]: Как сравнить пути ?
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.10.18 13:56
Оценка: -1
Здравствуйте, EreTIk, Вы писали:

ETI>В операционной системе именем на томе заведует драйвер файловой системы. Если файла нет, то (с учетом точек повторного разбора) у операционной системы нет возможности узнать на какой файловой системе расположен файл, следовательно, нет возможности нормализовать и сравнить имя.


Ну нет, конечно. Если хотя бы у одного файла существует директория, в которой он должен быть расположен, то пути эквиавалентны, если у второго файла тоже существует директория, и эти директории совпадают.

Если же оба пути указывают на несуществующую директорию, то надо для обеих путей найти самую "внутреннюю" существующую директорию, убедиться в том, что это именно директория, а не регулярный файл, привести обе директории к каноническому виду, и интерпретировать остаток путей относительно этих директорий. Если в результате получатся одинаковые пути, то пути совпадают.
Re[7]: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 14:09
Оценка: +1
Здравствуйте, Pzz, Вы писали:

Pzz>Ну нет, конечно. Если хотя бы у одного файла существует директория, в которой он должен быть расположен, то пути эквиавалентны, если у второго файла тоже существует директория, и эти директории совпадают.


Как матчить сами имена файлов-то, откидывая директории? Например если в качестве имени файла в первом случае было указано длинное имя, а во втором — короткое (8.3, отличающееся от короткого) (файл существует, но недоступен вам для открытия и получения у него имени)?

Pzz>Если же оба пути указывают на несуществующую директорию, то надо для обеих путей найти самую "внутреннюю" существующую директорию, убедиться в том, что это именно директория, а не регулярный файл, привести обе директории к каноническому виду, и интерпретировать остаток путей относительно этих директорий. Если в результате получатся одинаковые пути, то пути совпадают.


Опять же непонятно как интерпретировать остаток, учитывая короткие-длинные имена, чувствительность к регистру?
Re[8]: Как сравнить пути ?
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.10.18 14:37
Оценка:
Здравствуйте, EreTIk, Вы писали:

Pzz>>Ну нет, конечно. Если хотя бы у одного файла существует директория, в которой он должен быть расположен, то пути эквиавалентны, если у второго файла тоже существует директория, и эти директории совпадают.


ETI>Как матчить сами имена файлов-то, откидывая директории? Например если в качестве имени файла в первом случае было указано длинное имя, а во втором — короткое (8.3, отличающееся от короткого) (файл существует, но недоступен вам для открытия и получения у него имени)?


Буквально, с учетом чувствительности к регистру, характерной для той директории, где расположены файлы.

Pzz>>Если же оба пути указывают на несуществующую директорию, то надо для обеих путей найти самую "внутреннюю" существующую директорию, убедиться в том, что это именно директория, а не регулярный файл, привести обе директории к каноническому виду, и интерпретировать остаток путей относительно этих директорий. Если в результате получатся одинаковые пути, то пути совпадают.


ETI>Опять же непонятно как интерпретировать остаток, учитывая короткие-длинные имена, чувствительность к регистру?


Буквально, с учетом чувствительности к регистру, характерной для имеющейся существующей директории. Если они разные, ну, выбрать нечувствительное к регистру сравнение, как более характерное для вендов.

Этот способ не даст 100% точного ответа, но это будет гораздо более понятно пользователю, чем требование существование файла. Не надо забывать, что мы пишем программы для людей, а не для ЭВМ.
Re[5]: Как сравнить пути ?
От: kov_serg Россия  
Дата: 03.10.18 14:38
Оценка: -1
Здравствуйте, Pzz, Вы писали:

Pzz>Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.

Можно попросить у системы номер файла например
ULONGLONG GetFileIndex(LPCTSTR name) {
    HANDLE h;ULONGLONG id; BY_HANDLE_FILE_INFORMATION info;ZeroMemory(&info,sizeof(info));
    h=CreateFile(name,FILE_GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
    GetFileInformationByHandle(h,&info);
    id=info.nFileIndexHigh; id<<=32; id|=info.nFileIndexLow;
    CloseHandle(h);
    return id;
}

Если номера совпали то директории одинаковые, но есть нюансы.
Re[9]: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 14:48
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Этот способ не даст 100% точного ответа, но это будет гораздо более понятно пользователю, чем требование существование файла. Не надо забывать, что мы пишем программы для людей, а не для ЭВМ.


Мы пишем программы для разных задач. И от условий задачи будет зависит правильный способ решения задачи. Возможно, к примеру, по условию задачи будет корректным в качестве результата сравнения возвращать три варианта: совпадают, не совпадают и невозможно достоверно сравнить. Но условий задачи, к сожалению, в исходном сообщении не было. А был приведен пример с существующим директориями C:\Windows\System32 и \SystemRoot.
Re[6]: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 14:52
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Можно попросить у системы номер файла например

_>
_>ULONGLONG GetFileIndex(LPCTSTR name) {
_>    HANDLE h;ULONGLONG id; BY_HANDLE_FILE_INFORMATION info;ZeroMemory(&info,sizeof(info));
_>    h=CreateFile(name,FILE_GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
_>    GetFileInformationByHandle(h,&info);
_>    id=info.nFileIndexHigh; id<<=32; id|=info.nFileIndexLow;
_>    CloseHandle(h);
_>    return id;
_>}
_>

_>Если номера совпали то директории одинаковые, но есть нюансы.

Такой идентификатор уникален только в рамках одного тома, необходимо уметь сравнивать тома. В 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.


Хотя мне кажется что присутствие в системе двух томов с одинаковыми серийниками возможно.
Re[7]: Как сравнить пути ?
От: kov_serg Россия  
Дата: 03.10.18 15:13
Оценка:
Здравствуйте, EreTIk, Вы писали:

ETI>Здравствуйте, kov_serg, Вы писали:


_>>Можно попросить у системы номер файла например

_>>
_>>ULONGLONG GetFileIndex(LPCTSTR name) {
_>>    HANDLE h;ULONGLONG id; BY_HANDLE_FILE_INFORMATION info;ZeroMemory(&info,sizeof(info));
_>>    h=CreateFile(name,FILE_GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
_>>    GetFileInformationByHandle(h,&info);
_>>    id=info.nFileIndexHigh; id<<=32; id|=info.nFileIndexLow;
_>>    CloseHandle(h);
_>>    return id;
_>>}
_>>

_>>Если номера совпали то директории одинаковые, но есть нюансы.

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;
}
Re[8]: Как сравнить пути ?
От: EreTIk EreTIk's Box
Дата: 03.10.18 15:36
Оценка:
_>Не ну как вариант еще так можно
_>
_>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 может назначаться программно, значит двум файлам может быть назначен один и тот же идентификатор (специально или по ошибке).
Re[9]: Как сравнить пути ?
От: smbdnew  
Дата: 03.10.18 16:40
Оценка:
Ох и устроили :D
Сделал с zwcreatefile + zwqueryobject(objectnameinformation). Вроде и так пойдет.
Re[9]: Как сравнить пути ?
От: kov_serg Россия  
Дата: 03.10.18 17:02
Оценка:
Здравствуйте, EreTIk, Вы писали:

ETI>Кроме того, что FAT (как и некоторые другие ФС) не поддерживает такие идентификаторы файлов, есть FSCTL_SET_OBJECT_ID. То есть данный идентификатор на NTFS может назначаться программно, значит двум файлам может быть назначен один и тот же идентификатор (специально или по ошибке).

Некоторые другие файловые системы и symbolic link-и и mount-bind и собирать дирикторию из кучи других директорий умеют и что?
Даже в одной и той же винде одни приложения видят директорию c:\windows\system32\Microsoft а другие нет.

Если надо быстро и сердито все правила обрабатываем вручную. Если лень то GetFullPathName.
Для контроля методы с id и guid (но они могут надолго зависать на сетевых путях) и на крайняк можно в директории создать временный уникальный файл если хочеться удостовериться.

Как по мне я бы не заморачивался и считал бы все пути разными
Re[6]: Как сравнить пути ?
От: mike_rs Россия  
Дата: 03.10.18 19:15
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Pzz, Вы писали:


Pzz>>Вопрос, как раз, довольно очевидный: как проверить эквиавалентность двух путей со всеми этими тонкостями так, чтобы тонкостями занималась операционная система.

_>Можно попросить у системы номер файла например
_>
_>ULONGLONG GetFileIndex(LPCTSTR name) {
_>    HANDLE h;ULONGLONG id; BY_HANDLE_FILE_INFORMATION info;ZeroMemory(&info,sizeof(info));
_>    h=CreateFile(name,FILE_GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
_>    GetFileInformationByHandle(h,&info);
_>    id=info.nFileIndexHigh; id<<=32; id|=info.nFileIndexLow;
_>    CloseHandle(h);
_>    return id;
_>}
_>

_>Если номера совпали то директории одинаковые, но есть нюансы.
а если номеров нет? hint: далеко не все фс поддерживают уникальные номера.
Re[3]: Как сравнить пути ?
От: Masterspline  
Дата: 04.10.18 20:37
Оценка:
Pzz>Задача определения эквиалентности путей имеет смысл даже если соответствующих файлов не существует. Однако предложенный тобой способ не сработает в данной ситуации.

А если один файл существует, а второго нет, но если бы был, то был бы симлинком на первый?
Re[10]: Как сравнить пути ?
От: smbdnew  
Дата: 05.10.18 07:14
Оценка:
S>Сделал с zwcreatefile + zwqueryobject(objectnameinformation). Вроде и так пойдет.

Походу всё таки не пойдет. Может вернуть короткий путь (с тильдой) хотя путь сам по себе не длинный.

Здравствуйте, EreTIk, Вы писали:

ETI>Каков вопрос (насколько он полно задан) — таков ответ.

Мне надо сравнивать путь до папок. FltGetFileNameInformation выглядит многообещающе, но где взять PFILE_OBJECT — не знаю.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.