%% 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;
}