MCPcopy Create free account
hub / github.com/FirebirdSQL/firebird / getUniqueFileId

Function getUniqueFileId

src/common/os/win32/os_utils.cpp:411–562  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

409}
410
411void getUniqueFileId(HANDLE fd, UCharBuffer& id)
412{
413 entryLoader.init();
414 id.clear();
415
416 // Let's try getting the file identifier. It's not as easy as it may look.
417 // MSDN says: "After a process opens a file, the identifier is constant until
418 // the file is closed". So far so good, this is perfectly OK for us.
419 // But MSDN also says: "An application can use this identifier and the
420 // volume serial number to determine whether two handles refer to the same file".
421 // And this part is not true, unfortunately. Volume serial number (VSN) is not
422 // guaranteed to be unique. It's generated when then volume is formatted and
423 // it's stored inside the volume's master boot record. But if the volume is cloned
424 // at the physical block level, or if a virtual (preformatted) drive is used,
425 // or if volume snapshot is attached as a different logical volume, then VSN may
426 // duplicate an existing VSN. And we would stay confused thinking that two
427 // different files are actually the same file. To avoid such a disaster we
428 // retrieve the final pathname (with symlinks and mount points expanded)
429 // and extract the volume GUID (for local drives) or its share name
430 // (for remote drives) as unique volume ID.
431
432 if (fnGetFinalPathNameByHandle)
433 {
434 char pathbuf[MAX_PATH + 1];
435 DWORD res = fnGetFinalPathNameByHandle(fd,
436 pathbuf, sizeof(pathbuf), VOLUME_NAME_GUID);
437 if (res && res < sizeof(pathbuf))
438 {
439 string path(pathbuf);
440
441 // Expected format is \\?\Volume{GUID}\pathname,
442 // we extract {GUID} and convert into binary format
443
444 const char* const pattern = "\\\\?\\Volume";
445 const FB_SIZE_T pos1 = (FB_SIZE_T) strlen(pattern);
446
447 if (path.find(pattern) == 0)
448 {
449 const FB_SIZE_T pos2 = path.find_first_of('}');
450
451 if (path.find_first_of('{') == pos1 && pos2 != string::npos)
452 {
453 fb_assert(id.isEmpty());
454 id.resize(sizeof(Guid));
455 UCHAR* ptr = id.begin();
456 bool num_start = true;
457
458 for (FB_SIZE_T n = pos1 + 1; n < pos2 && ptr < id.end(); n++)
459 {
460 const char symbol = path[n];
461
462 if (symbol == '-')
463 continue;
464
465 fb_assert(isalpha(symbol) || isdigit(symbol));
466
467 if (symbol >= '0' && symbol <= '9')
468 *ptr += symbol - '0';

Callers

nothing calls this directly

Calls 10

raiseFunction · 0.85
initMethod · 0.45
clearMethod · 0.45
findMethod · 0.45
find_first_ofMethod · 0.45
isEmptyMethod · 0.45
resizeMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
addMethod · 0.45

Tested by

no test coverage detected