1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2015-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8%% header 9 10/** @file 11 Obtain unique file identifier for path specified as wchar_t string. 12 On non-Windows systems the UFI consists of inode number and 13 device number. On Windows systems the volume serial number, 14 higher index number and lower index number are used. 15 16 CRT on Windows: Not used. 17*/ 18 19#ifndef DK4CONF_H_INCLUDED 20#if DK4_BUILDING_DKTOOLS4 21#include "dk4conf.h" 22#else 23#include <dktools-4/dk4conf.h> 24#endif 25#endif 26 27#ifndef DK4UFI_H_INCLUDED 28#if DK4_BUILDING_DKTOOLS4 29#include <libdk4c/dk4ufit.h> 30#else 31#include <dktools-4/dk4ufit.h> 32#endif 33#endif 34 35#ifndef DK4ERROR_H_INCLUDED 36#if DK4_BUILDING_DKTOOLS4 37#include <libdk4base/dk4error.h> 38#else 39#include <dktools-4/dk4error.h> 40#endif 41#endif 42 43#ifdef __cplusplus 44extern "C" { 45#endif 46 47/** Retrieve unique file identifier. 48 For symbolic links on non-Windows systems, retrieve 49 information about the link target. 50 @param dptr Destination buffer. 51 @param fn File name. 52 @param erp Error report, may be NULL. 53 @return 1 on success, 0 on error. 54 55 Error codes: 56 - DK4_E_INVALID_ARGUMENTS<br> 57 if dptr or fn is NULL, 58 - DK4_E_SYSTEM<br> 59 with errno value stored in iDetails1 if the stat() function fails 60 on non-Windows systems, 61 - DK4_E_CREATE_FILE_FAILED<br> 62 with GetLastError() result in lDetails1 if the CreateFile() 63 function fails on Windows, 64 - DK4_E_FILE_INFORMATION_FAILED<br> 65 with GetLastError() result in lDetails1 if the 66 GetFileInformationByHandle() function fails on Windows. 67 - DK4_E_NOT_FOUND<br> 68 if the GetFileAttributes() function fails to retrieve file 69 attributes on Windows. 70 71*/ 72int 73dk4ufi_get_wc(dk4_ufi_t *dptr, const wchar_t *fn, dk4_er_t *erp); 74 75/** Retrieve unique file identifier. 76 For symbolic links on non-Windows systems, retrieve 77 information about the link. 78 @param dptr Destination buffer. 79 @param fn File name. 80 @param erp Error report, may be NULL. 81 @return 1 on success, 0 on error. 82 83 Error codes: 84 - DK4_E_INVALID_ARGUMENTS<br> 85 if dptr or fn is NULL, 86 - DK4_E_SYSTEM<br> 87 with errno value stored in iDetails1 if the lstat() function fails 88 on non-Windows systems, 89 - DK4_E_CREATE_FILE_FAILED<br> 90 with GetLastError() result in lDetails1 if the CreateFile() 91 function fails on Windows, 92 - DK4_E_FILE_INFORMATION_FAILED<br> 93 with GetLastError() result in lDetails1 if the 94 GetFileInformationByHandle() function fails on Windows. 95 - DK4_E_NOT_FOUND<br> 96 if the GetFileAttributes() function fails to retrieve file 97 attributes on Windows. 98*/ 99int 100dk4ufi_get_l_wc(dk4_ufi_t *dptr, const wchar_t *fn, dk4_er_t *erp); 101 102#ifdef __cplusplus 103} 104#endif 105 106 107 108%% module 109 110#include "dk4conf.h" 111 112#if DK4_ON_WINDOWS 113#ifndef WINDOWS_H_INCLUDED 114#include <windows.h> 115#define WINDOWS_H_INCLUDED 1 116#endif 117#endif 118 119#if DK4_HAVE_ASSERT_H 120#ifndef ASSERT_H_INCLUDED 121#include <assert.h> 122#define ASSERT_H_INCLUDED 1 123#endif 124#endif 125 126#include <libdk4c/dk4ufiwc.h> 127#include <libdk4base/dk4unused.h> 128 129 130 131int 132dk4ufi_get_wc( 133#if DK4_ON_WINDOWS 134 dk4_ufi_t *dptr, 135 const wchar_t *fn, 136#else 137 dk4_ufi_t * DK4_ARG_UNUSED(dptr), 138 const wchar_t * DK4_ARG_UNUSED(fn), 139#endif 140 dk4_er_t *erp 141) 142{ 143#if DK4_ON_WINDOWS 144 BY_HANDLE_FILE_INFORMATION bhfi; 145 WIN32_FIND_DATAW ffdata; 146 HANDLE han; 147 DWORD dwattr; 148 int i; 149 int back = 0; 150#if DK4_USE_ASSERT 151 assert(NULL != dptr); 152 assert(NULL != fn); 153#endif 154 if ((NULL != dptr) && (NULL != fn)) { 155 dwattr = GetFileAttributesW(fn); 156 if (INVALID_FILE_ATTRIBUTES == dwattr) { 157 han = FindFirstFileW(fn, &ffdata); 158 if (INVALID_HANDLE_VALUE != han) { 159 dwattr = ffdata.dwFileAttributes; 160 FindClose(han); 161 } 162 } 163 if (INVALID_FILE_ATTRIBUTES != dwattr) { 164 if (0 != (FILE_ATTRIBUTE_DIRECTORY & dwattr)) { 165 dwattr |= FILE_FLAG_BACKUP_SEMANTICS; 166 } 167 for (i = 0; ((2 > i) && (0 == back)); i++) { 168 han = CreateFileW( 169 fn, 170 ((0 == i) ? (0) : (GENERIC_READ)), 171 (FILE_SHARE_READ | FILE_SHARE_WRITE), 172 NULL, 173 OPEN_EXISTING, 174 dwattr, 175 NULL 176 ); 177 if (INVALID_HANDLE_VALUE != han) { 178 if (GetFileInformationByHandle(han, &bhfi)) { 179 back = 1; 180 dptr->ser = bhfi.dwVolumeSerialNumber; 181 dptr->inh = bhfi.nFileIndexHigh; 182 dptr->inl = bhfi.nFileIndexLow; 183 } else { 184 if (1 == i) { 185 /* ERROR */ 186 dk4error_set_ldetails( 187 erp, DK4_E_FILE_INFORMATION_FAILED, 188 (long)((unsigned long)GetLastError()) 189 ); 190 } 191 } 192 } else { 193 if (1 == i) { 194 /* ERROR */ 195 dk4error_set_ldetails( 196 erp, DK4_E_CREATE_FILE_FAILED, 197 (long)((unsigned long)GetLastError()) 198 ); 199 } 200 } 201 } 202 } else { 203 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); 204 } 205 } else { 206 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 207 } 208 return back; 209#else 210 DK4_UNUSED_ARG(dptr) 211 DK4_UNUSED_ARG(fn) 212 dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED); 213 return 0; 214#endif 215} 216 217 218 219int 220dk4ufi_get_l_wc( 221#if DK4_ON_WINDOWS 222 dk4_ufi_t *dptr, 223 const wchar_t *fn, 224#else 225 dk4_ufi_t * DK4_ARG_UNUSED(dptr), 226 const wchar_t * DK4_ARG_UNUSED(fn), 227#endif 228 dk4_er_t *erp 229) 230{ 231#if DK4_ON_WINDOWS 232 BY_HANDLE_FILE_INFORMATION bhfi; 233 WIN32_FIND_DATAW ffdata; 234 HANDLE han; 235 DWORD dwattr; 236 int i; 237 int back = 0; 238#if DK4_USE_ASSERT 239 assert(NULL != dptr); 240 assert(NULL != fn); 241#endif 242 if ((NULL != dptr) && (NULL != fn)) { 243 dwattr = GetFileAttributesW(fn); 244 if (INVALID_FILE_ATTRIBUTES == dwattr) { 245 han = FindFirstFileW(fn, &ffdata); 246 if (INVALID_HANDLE_VALUE != han) { 247 dwattr = ffdata.dwFileAttributes; 248 FindClose(han); 249 } 250 } 251 if (INVALID_FILE_ATTRIBUTES != dwattr) { 252 if (0 != (FILE_ATTRIBUTE_DIRECTORY & dwattr)) { 253 dwattr |= FILE_FLAG_BACKUP_SEMANTICS; 254 } 255 dwattr |= FILE_FLAG_OPEN_REPARSE_POINT; 256 for (i = 0; ((2 > i) && (0 == back)); i++) { 257 han = CreateFileW( 258 fn, 259 ((0 == i) ? (0) : (GENERIC_READ)), 260 (FILE_SHARE_READ | FILE_SHARE_WRITE), 261 NULL, 262 OPEN_EXISTING, 263 dwattr, 264 NULL 265 ); 266 if (INVALID_HANDLE_VALUE != han) { 267 if (GetFileInformationByHandle(han, &bhfi)) { 268 back = 1; 269 dptr->ser = bhfi.dwVolumeSerialNumber; 270 dptr->inh = bhfi.nFileIndexHigh; 271 dptr->inl = bhfi.nFileIndexLow; 272 } else { 273 if (1 == i) { 274 /* ERROR */ 275 dk4error_set_ldetails( 276 erp, DK4_E_FILE_INFORMATION_FAILED, 277 (long)((unsigned long)GetLastError()) 278 ); 279 } 280 } 281 } else { 282 if (1 == i) { 283 /* ERROR */ 284 dk4error_set_ldetails( 285 erp, DK4_E_CREATE_FILE_FAILED, 286 (long)((unsigned long)GetLastError()) 287 ); 288 } 289 } 290 } 291 } else { 292 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); 293 } 294 } else { 295 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 296 } 297 return back; 298#else 299 DK4_UNUSED_ARG(dptr) 300 DK4_UNUSED_ARG(fn) 301 dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED); 302 return 0; 303#endif 304} 305 306