summaryrefslogtreecommitdiff
path: root/support/dktools/dk3ufi.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk3ufi.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk3ufi.ctr')
-rw-r--r--support/dktools/dk3ufi.ctr423
1 files changed, 423 insertions, 0 deletions
diff --git a/support/dktools/dk3ufi.ctr b/support/dktools/dk3ufi.ctr
new file mode 100644
index 0000000000..fad652192e
--- /dev/null
+++ b/support/dktools/dk3ufi.ctr
@@ -0,0 +1,423 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2012-xxxx
+license = bsd
+
+
+%% header
+
+#include "dk3types.h"
+
+/** Unique file identifier.
+ If two files produce the same UFI they are both links
+ to the same file or different file name notations
+ pointing to the same file, i.e. "x.txt" and "./x.txt".
+*/
+typedef struct {
+#if DK3_ON_WINDOWS
+ DWORD volser; /**< Volume serial number. */
+ DWORD indhigh; /**< Higner index part. */
+ DWORD indlow; /**< Lower index part. */
+#else
+ dk3_um_t device; /**< Device number. */
+ dk3_um_t inode; /**< Inode number. */
+#endif
+} dk3_ufi_t;
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Obtain unique identifier for file.
+ @param pd Result buffer pointer.
+ @param fn File name to check.
+ @param app Application structure for diagnostics, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+int
+dk3ufi_get_app(dk3_ufi_t *pd, dkChar const *fn, dk3_app_t *app);
+
+/** Obtain unique identifier for file.
+ @param pd Result buffer pointer.
+ @param fn File name to check (8-bit character string).
+ @param app Application structure for diagnostics, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+int
+dk3ufi_c8_get_app(dk3_ufi_t *pd, char const *fn, dk3_app_t *app);
+
+/** Obtain unique identifier for file.
+ @param pd Result buffer pointer.
+ @param fn File name to check.
+ @return 1 on success, 0 on error.
+*/
+int
+dk3ufi_get(dk3_ufi_t *pd, dkChar const *fn);
+
+/** Obtain unique identifier for file.
+ @param pd Result buffer pointer.
+ @param fn File name to check (8-bit character string).
+ @return 1 on success, 0 on error.
+*/
+int
+dk3ufi_c8_get(dk3_ufi_t *pd, char const *fn);
+
+/** Compare two file identifiers.
+ @param l Left identifier.
+ @param r Right identifier.
+ @param cr Comparison criteria (ignored).
+ @return Comparison result.
+*/
+int
+dk3ufi_compare(void const *l, void const *r, int cr);
+
+#ifdef __cplusplus
+}
+#endif
+
+%% module
+
+#include "dk3all.h"
+#include "dk3ufi.h"
+
+
+
+$!trace-include
+
+
+
+int
+dk3ufi_get_app(dk3_ufi_t *pd, dkChar const *fn, dk3_app_t *app)
+{
+#if DK3_ON_WINDOWS
+ BY_HANDLE_FILE_INFORMATION bhfi;
+#endif
+ dk3_stat_t stb;
+#if DK3_ON_WINDOWS
+ HANDLE hFile;
+ int i;
+#endif
+ int back = 0;
+ $? "+ dk3ufi_get_app \"%!ds\"", TR_STR(fn)
+ if((pd) && (fn)) {
+ if(dk3sf_stat_app(&stb, fn, app)) {
+ switch(stb.ft & (~(DK3_FT_SYMLINK))) {
+ case DK3_FT_REGULAR: {
+#if DK3_ON_WINDOWS
+ for(i = 0; ((i < 2) && (0 == back)); i++) {
+#if DK3_CHAR_SIZE > 2
+ hFile = INVALID_HANDLE_VALUE;
+#else
+#if DK3_CHAR_SIZE > 1
+ $? ". wide \"%ls\"", fn
+ hFile = CreateFileW(
+ fn,
+ ((0 == i) ? (FILE_READ_ATTRIBUTES) : 0),
+ (FILE_SHARE_READ),
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+#else
+ $? ". ascii"
+ hFile = CreateFileA(
+ fn,
+ ((0 == i) ? (FILE_READ_ATTRIBUTES) : 0),
+ (FILE_SHARE_READ),
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+#endif
+#endif
+ if(INVALID_HANDLE_VALUE != hFile) {
+ if(GetFileInformationByHandle(hFile, &bhfi)) {
+ back = 1; $? ". success %d", i
+ i = 2;
+ pd->volser = bhfi.dwVolumeSerialNumber;
+ pd->indhigh = bhfi.nFileIndexHigh;
+ pd->indlow = bhfi.nFileIndexLow;
+ } else {
+ /* ERROR: Failed to obtain file information! */
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+ }
+ CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
+ } else {
+ /* ERROR: Failed to obtain file information! */
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+ }
+ }
+#else
+ pd->device = stb.device;
+ pd->inode = stb.inode;
+ back = 1;
+#endif
+ } break;
+ case DK3_FT_DIRECTORY: { $? ". directory"
+#if DK3_ON_WINDOWS
+ for(i = 0; ((i < 2) && (0 == back)); i++) {
+#if DK3_CHAR_SIZE > 2
+ hFile = INVALID_HANDLE_VALUE;
+#else
+#if DK3_CHAR_SIZE > 1
+ $? ". wide \"%ls\"", fn
+ hFile = CreateFileW(
+ fn,
+ ((0 == i) ? (FILE_READ_ATTRIBUTES) : 0),
+ (FILE_SHARE_READ),
+ NULL,
+ OPEN_EXISTING,
+ (FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS),
+ NULL
+ );
+#else
+ $? ". ascii"
+ hFile = CreateFileA(
+ fn,
+ ((0 == i) ? (FILE_READ_ATTRIBUTES) : 0),
+ (FILE_SHARE_READ),
+ NULL,
+ OPEN_EXISTING,
+ (FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS),
+ NULL
+ );
+#endif
+#endif
+ if(INVALID_HANDLE_VALUE != hFile) {
+ if(GetFileInformationByHandle(hFile, &bhfi)) {
+ back = 1; $? ". success %d", i
+ i = 2;
+ pd->volser = bhfi.dwVolumeSerialNumber;
+ pd->indhigh = bhfi.nFileIndexHigh;
+ pd->indlow = bhfi.nFileIndexLow;
+ } else { $? "! GetFile... %ld", (long)GetLastError()
+ /* ERROR: Failed to obtain file information! */
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+ }
+ CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
+ } else { $? "! CreateFile %ld", (long)GetLastError()
+ /* ERROR: Failed to obtain file information */
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+ }
+ }
+#else
+ pd->device = stb.device;
+ pd->inode = stb.inode;
+ back = 1;
+#endif
+ } break;
+ default: { $? "! not a regular file"
+ } break;
+ }
+ } else { $? "! stat"
+ }
+ } else { $? "! arguments"
+ } $? "- dk3ufi_get_app %d", back
+ return back;
+}
+
+
+
+int
+dk3ufi_c8_get_app(dk3_ufi_t *pd, char const *fn, dk3_app_t *app)
+{
+#if DK3_ON_WINDOWS
+ BY_HANDLE_FILE_INFORMATION bhfi;
+#endif
+ dk3_stat_t stb;
+#if DK3_ON_WINDOWS
+ HANDLE hFile;
+ int i;
+#endif
+ int back = 0;
+ $? "+ dk3ufi_c8_get_app %!8s", TR_8STR(fn)
+ if((pd) && (fn)) {
+ if(dk3sf_c8_stat_app(&stb, fn, app)) {
+ switch(stb.ft & (~(DK3_FT_SYMLINK))) {
+ case DK3_FT_REGULAR: {
+#if DK3_ON_WINDOWS
+ for(i = 0; ((i < 2) && (0 == back)); i++) {
+ $? ". ascii"
+ hFile = CreateFileA(
+ fn,
+ ((0 == i) ? (FILE_READ_ATTRIBUTES) : 0),
+ (FILE_SHARE_READ),
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if(INVALID_HANDLE_VALUE != hFile) {
+ if(GetFileInformationByHandle(hFile, &bhfi)) {
+ back = 1; $? ". success %d", i
+ i = 2;
+ pd->volser = bhfi.dwVolumeSerialNumber;
+ pd->indhigh = bhfi.nFileIndexHigh;
+ pd->indlow = bhfi.nFileIndexLow;
+ } else {
+ /* ERROR: Failed to obtain file information! */
+#if DK3_CHAR_SIZE == 1
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+#else
+ dk3app_log_i1(app, DK3_LL_ERROR, 368);
+#endif
+ }
+ CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
+ } else {
+ /* ERROR: Failed to obtain file information! */
+#if DK3_CHAR_SIZE == 1
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+#else
+ dk3app_log_i1(app, DK3_LL_ERROR, 368);
+#endif
+ }
+ }
+#else
+ pd->device = stb.device;
+ pd->inode = stb.inode;
+ back = 1;
+#endif
+ } break;
+ case DK3_FT_DIRECTORY: { $? ". directory"
+#if DK3_ON_WINDOWS
+ for(i = 0; ((i < 2) && (0 == back)); i++) {
+ $? ". ascii"
+ hFile = CreateFileA(
+ fn,
+ ((0 == i) ? (FILE_READ_ATTRIBUTES) : 0),
+ (FILE_SHARE_READ),
+ NULL,
+ OPEN_EXISTING,
+ (FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS),
+ NULL
+ );
+ if(INVALID_HANDLE_VALUE != hFile) {
+ if(GetFileInformationByHandle(hFile, &bhfi)) {
+ back = 1; $? ". success %d", i
+ i = 2;
+ pd->volser = bhfi.dwVolumeSerialNumber;
+ pd->indhigh = bhfi.nFileIndexHigh;
+ pd->indlow = bhfi.nFileIndexLow;
+ } else { $? "! GetFile... %ld", (long)GetLastError()
+ /* ERROR: Failed to obtain file information! */
+#if DK3_CHAR_SIZE == 1
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+#else
+ dk3app_log_i1(app, DK3_LL_ERROR, 368);
+#endif
+ }
+ CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
+ } else { $? "! CreateFile %ld", (long)GetLastError()
+ /* ERROR: Failed to obtain file information! */
+#if DK3_CHAR_SIZE == 1
+ dk3app_log_i3(app, DK3_LL_ERROR, 366, 367, fn);
+#else
+ dk3app_log_i1(app, DK3_LL_ERROR, 368);
+#endif
+ }
+ }
+#else
+ pd->device = stb.device;
+ pd->inode = stb.inode;
+ back = 1;
+#endif
+ } break;
+ default: { $? "! not a regular file"
+ } break;
+ }
+ } else { $? "! stat"
+ }
+ } else { $? "! arguments"
+ } $? "- dk3ufi_get_app %d", back
+ $? "- dk3ufi_c8_get_app %d", back
+ return back;
+}
+
+
+
+int
+dk3ufi_get(dk3_ufi_t *pd, dkChar const *fn)
+{
+ int back;
+ back = dk3ufi_get_app(pd, fn, NULL);
+ return back;
+}
+
+
+
+int
+dk3ufi_c8_get(dk3_ufi_t *pd, char const *fn)
+{
+ int back;
+ back = dk3ufi_c8_get_app(pd, fn, NULL);
+ return back;
+}
+
+
+
+int
+dk3ufi_compare(void const *l, void const *r, int cr)
+{
+ int back = 0;
+ dk3_ufi_t const *pl;
+ dk3_ufi_t const *pr;
+ if(l) {
+ if(r) {
+ pl = (dk3_ufi_t const *)l; pr = (dk3_ufi_t const *)r;
+#if DK3_ON_WINDOWS
+ if(pl->volser < pr->volser) {
+ back = -1;
+ } else {
+ if(pl->volser > pr->volser) {
+ back = 1;
+ }
+ }
+ if(0 == back) {
+ if(pl->indhigh < pr->indhigh) {
+ back = -1;
+ } else {
+ if(pl->indhigh > pr->indhigh) {
+ back = 1;
+ }
+ }
+ }
+ if(0 == back) {
+ if(pl->indlow < pr->indlow) {
+ back = -1;
+ } else {
+ if(pl->indlow > pr->indlow) {
+ back = 1;
+ }
+ }
+ }
+#else
+ if(pl->device < pr->device) {
+ back = -1;
+ } else {
+ if(pl->device > pr->device) {
+ back = 1;
+ }
+ }
+ if(0 == back) {
+ if(pl->inode < pr->inode) {
+ back = -1;
+ } else {
+ if(pl->inode > pr->inode) {
+ back = 1;
+ }
+ }
+ }
+#endif
+ } else back = 1;
+ } else {
+ if(r) back = -1;
+ }
+ return back;
+}
+
+