%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Functions for file information. */ #ifndef DK4FILEIT_H_INCLUDED #include "dk4fileit.h" #endif #ifndef DK4UFI_H_INCLUDED #include "dk4ufi.h" #endif #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif #ifdef __cplusplus extern "C" { #endif /** Initialize a file information structure. @param dptr File information structure to initialize. */ void dk4fileinfo_init(dk4_file_info_t *dptr); /** Retrieve full information for a path name. For symbolic links attempt to retrieve information both about the link and about the link target. CRT on Windows: Not used. @param dptr Pointer to result structure. @param fn File path name. @param erp Error report, may be NULL. @return 1 if information is found, 0 otherwise. If information about the link is found and no information about the target, the function returns 1 as we can recognize the directory item as a dangling link (link with non-existing target). Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fn is NULL, - DK4_E_SYSTEM
with errno value stored in iDetails1 if the stat() function fails on non-Windows systems. - DK4_E_SYSTEM
with GetLastError() value stored in lDetails1 if the GetFileAttributes() function failed, - DK4_E_CREATE_FILE_FAILED
with GetLastError() value stored in lDetails1 if the CreateFile() function failed on Windows systems, - DK4_E_FILE_INFORMATION_FAILED
with GetLastError() value stored in lDetails1 if the GetFileInformationByHandle() function failed on Windows systems, - DK4_E_FINDFIRSTFILE_FAILED
with GetLastError() value stored in lDetails1 if the FindFirstFile() function failed on Windows systems. */ int dk4fileinfo_c8(dk4_file_info_t *dptr, const char *fn, dk4_er_t *erp); /** Retrieve full information for a path name. For symbolic links attempt to retrieve information both about the link and about the link target. CRT on Windows: Not used. @param dptr Pointer to result structure. @param fn File path name. @param erp Error report, may be NULL. @return 1 if information is found, 0 otherwise. If information about the link is found and no information about the target, the function returns 1 as we can recognize the directory item as a dangling link (link with non-existing target). Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fn is NULL, - DK4_E_SYSTEM
with errno value stored in iDetails1 if the stat() function fails on non-Windows systems. - DK4_E_SYSTEM
with GetLastError() value stored in lDetails1 if the GetFileAttributes() function failed, - DK4_E_CREATE_FILE_FAILED
with GetLastError() value stored in lDetails1 if the CreateFile() function failed on Windows systems, - DK4_E_FILE_INFORMATION_FAILED
with GetLastError() value stored in lDetails1 if the GetFileInformationByHandle() function failed on Windows systems, - DK4_E_FINDFIRSTFILE_FAILED
with GetLastError() value stored in lDetails1 if the FindFirstFile() function failed on Windows systems. */ int dk4fileinfo_wc(dk4_file_info_t *dptr, const wchar_t *fn, dk4_er_t *erp); /** Retrieve full information for a path name. For symbolic links attempt to retrieve information both about the link and about the link target. CRT on Windows: Not used. @param dptr Pointer to result structure. @param fn File path name. @param erp Error report, may be NULL. @return 1 if information is found, 0 otherwise. If information about the link is found and no information about the target, the function returns 1 as we can recognize the directory item as a dangling link (link with non-existing target). Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fn is NULL, - DK4_E_SYSTEM
with errno value stored in iDetails1 if the stat() function fails on non-Windows systems. - DK4_E_SYSTEM
with GetLastError() value stored in lDetails1 if the GetFileAttributes() function failed, - DK4_E_CREATE_FILE_FAILED
with GetLastError() value stored in lDetails1 if the CreateFile() function failed on Windows systems, - DK4_E_FILE_INFORMATION_FAILED
with GetLastError() value stored in lDetails1 if the GetFileInformationByHandle() function failed on Windows systems, - DK4_E_FINDFIRSTFILE_FAILED
with GetLastError() value stored in lDetails1 if the FindFirstFile() function failed on Windows systems. */ int dk4fileinfo(dk4_file_info_t *dptr, const dkChar *fn, dk4_er_t *erp); /** Retrieve timestamp from file information structure. @param dptr Destination buffer pointer. @param szdptr Destination buffer size. @param fi File information structure. @param chfile For symolic links, choose information source: DK4_FILE_INFO_CONTENTS_DATA_LINK for the link itself, DK4_FILE_INFO_CONTENTS_DATA_TARGET for the link target. @param chtime Choose timestamp: DK4_FILE_INFO_TIME_CREATE for creation time, DK4_FILE_INFO_TIME_MODIFY for modification time, DK4_FILE_INFO_TIME_ACCESS for last access time. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL or szdptr is 0, - DK4_E_NOT_FOUND
if the required information is not found in the file information structure. */ int dk4fileinfo_timestamp_c8( char *dptr, size_t szdptr, const dk4_file_info_t *fi, int chfile, int chtime, dk4_er_t *erp ); /** Retrieve timestamp from file information structure. @param dptr Destination buffer pointer. @param szdptr Destination buffer size (number of wchar_t). @param fi File information structure. @param chfile For symolic links, choose information source: DK4_FILE_INFO_CONTENTS_DATA_LINK for the link itself, DK4_FILE_INFO_CONTENTS_DATA_TARGET for the link target. @param chtime Choose timestamp: DK4_FILE_INFO_TIME_CREATE for creation time, DK4_FILE_INFO_TIME_MODIFY for modification time, DK4_FILE_INFO_TIME_ACCESS for last access time. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL or szdptr is 0, - DK4_E_NOT_FOUND
if the required information is not found in the file information structure. */ int dk4fileinfo_timestamp_wc( wchar_t *dptr, size_t szdptr, const dk4_file_info_t *fi, int chfile, int chtime, dk4_er_t *erp ); /** Retrieve timestamp from file information structure. @param dptr Destination buffer pointer. @param szdptr Destination buffer size (number of dkChar). @param fi File information structure. @param chfile For symolic links, choose information source: DK4_FILE_INFO_CONTENTS_DATA_LINK for the link itself, DK4_FILE_INFO_CONTENTS_DATA_TARGET for the link target. @param chtime Choose timestamp: DK4_FILE_INFO_TIME_CREATE for creation time, DK4_FILE_INFO_TIME_MODIFY for modification time, DK4_FILE_INFO_TIME_ACCESS for last access time. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL or szdptr is 0, - DK4_E_NOT_FOUND
if the required information is not found in the file information structure. */ int dk4fileinfo_timestamp( dkChar *dptr, size_t szdptr, const dk4_file_info_t *fi, int chfile, int chtime, dk4_er_t *erp ); /** Retrieve file type and attributes (file attributes on Windows, permissions on other systems). @param dptr Destination buffer address. @param szdptr Destination buffer size. @param fi File information structure. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL or szdptr is 0, - DK4_E_NOT_FOUND
if the required information is not available in the file information. */ int dk4fileinfo_type_attributes_c8( char *dptr, size_t szdptr, dk4_file_info_t *fi, dk4_er_t *erp ); /** Retrieve file type and attributes (file attributes on Windows, permissions on other systems). @param dptr Destination buffer address. @param szdptr Destination buffer size (number of wchar_t). @param fi File information structure. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL or szdptr is 0, - DK4_E_NOT_FOUND
if the required information is not available in the file information. */ int dk4fileinfo_type_attributes_wc( wchar_t *dptr, size_t szdptr, dk4_file_info_t *fi, dk4_er_t *erp ); /** Retrieve file type and attributes (file attributes on Windows, permissions on other systems). @param dptr Destination buffer address. @param szdptr Destination buffer size (number of dkChar). @param fi File information structure. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL or szdptr is 0, - DK4_E_NOT_FOUND
if the required information is not available in the file information. */ int dk4fileinfo_type_attributes( dkChar *dptr, size_t szdptr, dk4_file_info_t *fi, dk4_er_t *erp ); /** Retrieve unique file identifier from file information structure. @param dptr Pointer to destination variable. @param src File information structure to retrieve information from. @param ch For symbolic links choose between information for link itself (DK4_FILE_INFO_CONTENTS_DATA_LINK) or link target (DK4_FILE_INFO_CONTENTS_DATA_TARGET). @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or src is NULL, - DK4_E_NOT_FOUND
if the information is not present in the file information structure. */ int dk4fileinfo_ufi( dk4_ufi_t *dptr, const dk4_file_info_t *src, int ch, dk4_er_t *erp ); /** Check whether the file information structure represents a symbolic link. @param dptr File information structure to check. @return 1 for symbolic links, 0 otherwise. */ int dk4fileinfo_is_symlink(const dk4_file_info_t *dptr); /** Retrieve file size. @param dptr Pointer to result variable. @param fi File information structure. @param ch Choose information source for symbolic links: DK4_FILE_INFO_CONTENTS_DATA_LINK for the size of the link itself, DK4_FILE_INFO_CONTENTS_DATA_TARGET for the size of the link target. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or fi is NULL, - DK4_E_NOT_FOUND
if the required information is not available in the file information structure, - DK4_E_MATH_OVERFLOW
if the size calculation results in a numeric overflow. */ int dk4fileinfo_size( dk4_um_t *dptr, const dk4_file_info_t *fi, int ch, dk4_er_t *erp ); /** Check whether the file exists and is a regular file. For a symbolic link, the target must exist and be a regular file. @param fi File information already obtained for the file. @param erp Error report, may be NULL. @return 1 if the file exists and is a regular file. Error codes: - DK4_E_INVALID_ARGUMENTS
if fi is NULL. */ int dk4fileinfo_exists_and_is_regular(const dk4_file_info_t *fi, dk4_er_t *erp); #ifdef __cplusplus } #endif %% module #include "dk4filei.h" #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4MAADU_H_INCLUDED #include "dk4maadu.h" #endif $!trace-include void dk4fileinfo_init(dk4_file_info_t *dptr) { if (NULL != dptr) { DK4_MEMRES(dptr, sizeof(dk4_file_info_t)); dptr->contents = 0; } } int dk4fileinfo_is_symlink(const dk4_file_info_t *dptr) { int back = 0; if (NULL != dptr) { if (0 != (DK4_FILE_INFO_CONTENTS_DATA_LINK & (dptr->contents))) { #if DK4_ON_WINDOWS if (0 != (FILE_ATTRIBUTE_REPARSE_POINT & (dptr->fattr))) { if (IO_REPARSE_TAG_MOUNT_POINT == dptr->rppnt) { back = 1; } if (IO_REPARSE_TAG_SYMLINK == dptr->rppnt) { back = 1; } } #else #if defined(S_IFMT) && defined (S_IFLNK) if (S_IFLNK == (S_IFMT & ((dptr->lstb).st_mode))) { back = 1; } #endif #endif } } return back; } #if DK4_ON_WINDOWS static int dk4fileinfo_copy_size( dk4_um_t *dptr, const BY_HANDLE_FILE_INFORMATION *bhfi, dk4_er_t *erp ) { dk4_er_t er; dk4_um_t val; int back = 0; $? "+ dk4fileinfo_copy_size" dk4error_init(&er); $? ". high %lu", (unsigned long)(bhfi->nFileSizeHigh) $? ". low %lu", (unsigned long)(bhfi->nFileSizeLow) if ((DWORD)0UL != bhfi->nFileSizeHigh) { val = dk4ma_um_add( dk4ma_um_mul( dk4ma_um_add( (dk4_um_t)0xFFFFFFFFUL, (dk4_um_t)1UL, &er ), (dk4_um_t)(bhfi->nFileSizeHigh), &er ), (dk4_um_t)(bhfi->nFileSizeLow), &er ); } else { val = (dk4_um_t)(bhfi->nFileSizeLow); } if (DK4_E_NONE == er.ec) { $? ". no overflow" back = 1; *dptr = val; } else { $? "! overflow" dk4error_copy(erp, &er); } $? "- dk4fileinfo_copy_size %d", back return back; } #else static int dk4fileinfo_copy_size( dk4_um_t *dptr, const dk4_stat_t *stb, dk4_er_t *erp ) { *dptr = (dk4_um_t)(stb->st_size); return 1; } #endif int dk4fileinfo_size( dk4_um_t *dptr, const dk4_file_info_t *fi, int ch, dk4_er_t *erp ) { dk4_er_t er; int back = 0; $? "+ dk4fileinfo_size" if ((NULL != dptr) && (NULL != fi)) { $? ". args ok" dk4error_init(&er); switch (ch) { case DK4_FILE_INFO_CONTENTS_DATA_LINK: { $? ". link" if (0 != ((fi->contents) & DK4_FILE_INFO_CONTENTS_DATA_LINK)) { #if DK4_ON_WINDOWS $? ". windows" back = dk4fileinfo_copy_size(dptr, &(fi->linfo), &er); #else $? ". non-Windows" back = dk4fileinfo_copy_size(dptr, &(fi->lstb), &er); #endif } else { $? "! no data stored" dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } break; default: { $? ". link target" if (0 != ((fi->contents) & DK4_FILE_INFO_CONTENTS_DATA_TARGET)) { #if DK4_ON_WINDOWS $? ". Windows" back = dk4fileinfo_copy_size(dptr, &(fi->tinfo), &er); #else $? ". non-Windows" back = dk4fileinfo_copy_size(dptr, &(fi->tstb), &er); #endif } else { $? "! no data stored" dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } break; } if (0 != back) { dk4error_copy(erp, &er); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4fileinfo_size %d", back return back; } int dk4fileinfo_exists_and_is_regular(const dk4_file_info_t *fi, dk4_er_t *erp) { int back = 0; if (NULL != fi) { #if DK4_ON_WINDOWS if (0 != (DK4_FILE_INFO_CONTENTS_DATA_LINK & (fi->contents))) { if ((DWORD)0UL == (FILE_ATTRIBUTE_DIRECTORY & fi->fattr)) { if ((DWORD)0UL == (FILE_ATTRIBUTE_DEVICE & fi->fattr)) { back = 1; } } } #else if (0 != (DK4_FILE_INFO_CONTENTS_DATA_TARGET & (fi->contents))) { if (S_IFREG == (S_IFMT & ((fi->tstb).st_mode))) { back = 1; } } #endif } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; }