/* Copyright (c) 2000-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dksf.c System functions. */ #include "dk.h" #include "dktypes.h" #include "dksfc.h" #include "dkmem.h" #include "dkstr.h" #include "dkerror.h" #include $(trace-include) #if DK_HAVE_DOS_H #include #endif #if DK_HAVE_IO_H #include #endif #if DK_HAVE_STDLIB_H #include #endif #if DK_HAVE_STDDEF_H #include #endif #if DK_HAVE_STRING_H #include #endif #if DK_HAVE_SYS_TYPES_H #include #endif #if DK_HAVE_SYS_UIO_H #include #endif #if DK_HAVE_SYS_STAT_H #include #endif #if DK_HAVE_SYS_SYSTEMINFO_H #include #endif #if DK_HAVE_SYS_PARAM_H #include #endif #if DK_HAVE_SYS_RESOURCE_H #include #endif #if DK_HAVE_FCNTL_H #include #endif #if DK_HAVE_TERMIOS_H #include #endif #if DK_HAVE_SYS_TERMIOS_H #include #endif #if DK_HAVE_SYS_TTOLD_H #include #endif #if DK_HAVE_WINCON_H #include #endif #if DK_HAVE_UNISTD_H #include #endif #if DK_HAVE_DIRECT_H #include #endif #if DK_HAVE_DIRENT_H #include #endif #if DK_HAVE_DIR_H #include #endif #if DK_HAVE_PWD_H #include #endif #if DK_HAVE_PROCESS_H #include #endif #include "dkwin.h" #if DK_HAVE_ERRNO_H #include #endif #include "dkmem.h" /** Inside the dksf module. */ #define DK_SYSFCT_C 1 #include "dksf.h" /** Abbreviation for tm. */ typedef struct tm STRUCTTM; #ifdef MY_MAXPATHLEN #undef MY_MAXPATHLEN #endif #ifdef MAXPATHLEN /** Maximum path length. */ #define MY_MAXPATHLEN MAXPATHLEN #else #ifdef _MAX_PATH /** Maximum path length. */ #define MY_MAXPATHLEN _MAX_PATH #else /** Maximum path length. */ #define MY_MAXPATHLEN 1024L #endif #endif /** Separator between path components. */ static char path_component_separator[] = { #if DK_HAVE_FEATURE_BACKSLASH "\\" #else "/" #endif }; /** Other delimiter, not a separator between path components. */ static char no_component_separator[] = { #if DK_HAVE_FEATURE_BACKSLASH "/" #else "\\" #endif }; /** The /var/run directory. */ static char var_run[] = { DK_LOCALSTATEDIR "/run" }; /** Suffix to use for PID files. */ static char suffix_pid[] = { ".pid" }; #ifdef USE_FNE #undef USE_FNE #endif #if defined(WIN32) || defined(_WIN32) /* + Win32 */ #if DK_HAVE__FINDFIRST64 /* Win32, _findfirst64 */ /** Flag: Use file name expander. */ #define USE_FNE 1 #else #if DK_HAVE__FINDFIRST32 /* Win32, _findfirst32 */ /** Flag: Use file name expander. */ #define USE_FNE 1 #else #if DK_HAVE__FINDFIRST /* Win32, _findfirst */ /** Flag: Use file name expander. */ #define USE_FNE 1 #endif #endif #endif /* - Win32 */ #else #if DK_HAVE_FINDFIRST /* DOS, findfirst */ /** Flag: Use file name expander. */ #define USE_FNE 1 #else #if DK_HAVE_DIRENT_H /* UNIX/Linux, dirent */ /** Flag: Do not use file name expander. */ #define USE_FNE 0 #else /* any unknown directory listing mechanism */ /** Flag: Do not use file name expander. */ #define USE_FNE 0 #endif #endif #endif #if USE_FNE /** Pattern to match all files in the current directory. */ static char all_files[] = { #if DK_HAVE_ALLDOTALL "*.*" #else "*" #endif }; #endif #if DK_HAVE_FEATURE_DOS_EXEC /** Default PATH extensions on DOS and followers. */ static char default_path_ext[] = { ".COM;.EXE;.BAT" }; #endif #if DK_HAVE_FEATURE_BACKSLASH /** Default temporary directory on DOS and followers. */ static char temp_string[] = { "\\TEMP" }; #endif /** Time format to show file times. */ static char time_format[] = { "%04d/%02d/%02d %02d:%02d:%02d" }; /** File name of current working directory. */ static char curdir[] = { "." }; #if DK_HAVE_DOS_DRIVE_LETTER /** Colon, used to construct path names. */ static char str_colon = ':'; #endif #ifndef S_IFMT /** File mask. */ #ifdef _S_IFMT #define S_IFMT (_S_IFMT) #else #define S_IFMT 0170000 #endif #endif #ifndef S_IFREG /** File type: Regular file. */ #ifdef _S_IFREG #define S_IFREG (_S_IFREG) #else #define S_IFREG 0100000 #endif #endif #ifndef S_IFSOCK /** File type: Socket. */ #ifdef _S_IFSOCK #define S_IFSOCK (_S_IFSOCK) #else #define S_IFSOCK 0140000 #endif #endif #ifndef S_IFLNK /** File type: Symbolic link. */ #ifdef _S_IFLNK #define S_IFLNK (_S_IFLNK) #else #define S_IFLNK 0120000 #endif #endif #ifndef S_IFBLK /** File type: Block device. */ #ifdef _S_IFBLK #define S_IFBLK (_S_IFBLK) #else #define S_IFBLK 0060000 #endif #endif #ifndef S_IFDIR /** File type: Directory. */ #ifdef _S_IFDIR #define S_IFDIR (_S_IFDIR) #else #define S_IFDIR 0040000 #endif #endif #ifndef S_IFCHR /** File type: Character device. */ #ifdef _S_IFCHR #define S_IFCHR (_S_IFCHR) #else #define S_IFCHR 0020000 #endif #endif #ifndef S_IFIFO /** File type: FIFO. */ #ifdef _S_IFIFO #define S_IFIFO (_S_IFIFO) #else #define S_IFIFO 0010000 #endif #endif /** Convert native file type to DK_FT_xxx file type. @param m Native file type. @return DK_FT_xxx file type. */ static int dksf_filetype DK_P1(mode_t, m) { int back, found; $? "+ dksf_filetype %d", m back = found = 0; switch(m & S_IFMT) { case S_IFSOCK : back = DK_FT_SOCKET ; break; case S_IFLNK : back = DK_FT_SYMLINK ; break; case S_IFREG : back = DK_FT_REG; break; case S_IFBLK : back = DK_FT_BLK; break; case S_IFDIR : back = DK_FT_DIR; break; case S_IFCHR : back = DK_FT_CHR; break; default: back = DK_FT_OTHER; break; } $? "- dksf_filetype %d", back return back; } /** Convert DK_PERM_xxx permissions to native permissions. @param m DK_PERM_xxx permissions. @return Native permissions. */ mode_t dksf_perm_dk2h DK_P1(int, m) { mode_t back = 0L; $? "+ dksf_perm_dk2h %o", m if(m & DK_PERM_SUID) { #ifdef S_ISUID back |= S_ISUID; #else #ifdef _S_ISUID back |= _S_ISUID; #else back |= DK_PERM_SUID; #endif #endif } if(m & DK_PERM_SGID) { #ifdef S_ISGID back |= S_ISGID; #else #ifdef _S_ISGID back |= _S_ISGID; #else back |= DK_PERM_SGID; #endif #endif } if(m & DK_PERM_VTX) { #ifdef S_ISVTX back |= S_ISVTX; #else #ifdef _S_ISVTX back |= _S_ISVTX; #else back |= DK_PERM_VTX; #endif #endif } if(m & DK_PERM_U_READ) { #ifdef S_IRUSR back |= S_IRUSR; #else #ifdef _S_IRUSR back |= _S_IRUSR; #else back |= DK_PERM_U_READ; #endif #endif } if(m & DK_PERM_U_WRITE) { #ifdef S_IWUSR back |= S_IWUSR; #else #ifdef _S_IWUSR back |= _S_IWUSR; #else back |= DK_PERM_U_WRITE; #endif #endif } if(m & DK_PERM_U_EXECUTE) { #ifdef S_IXUSR back |= S_IXUSR; #else #ifdef _S_IXUSR back |= _S_IXUSR; #else back |= DK_PERM_U_EXECUTE; #endif #endif } if(m & DK_PERM_G_READ) { #ifdef S_IRGRP back |= S_IRGRP; #else #ifdef _S_IRGRP back |= _S_IRGRP; #else back |= DK_PERM_G_READ; #endif #endif } if(m & DK_PERM_G_WRITE) { #ifdef S_IWGRP back |= S_IWGRP; #else #ifdef _S_IWGRP back |= _S_IWGRP; #else back |= DK_PERM_G_WRITE; #endif #endif } if(m & DK_PERM_G_EXECUTE) { #ifdef S_IXGRP back |= S_IXGRP; #else #ifdef _S_IXGRP back |= _S_IXGRP; #else back |= DK_PERM_G_EXECUTE; #endif #endif } if(m & DK_PERM_O_READ) { #ifdef S_IROTH back |= S_IROTH; #else #ifdef _S_IROTH back |= _S_IROTH; #else back |= DK_PERM_O_READ; #endif #endif } if(m & DK_PERM_O_WRITE) { #ifdef S_IWOTH back |= S_IWOTH; #else #ifdef _S_IWOTH back |= _S_IWOTH; #else back |= DK_PERM_O_WRITE; #endif #endif } if(m & DK_PERM_O_EXECUTE) { #ifdef S_IXOTH back |= S_IXOTH; #else #ifdef _S_IXOTH back |= _S_IXOTH; #else back |= DK_PERM_O_EXECUTE; #endif #endif } $? "- dksf_perm_dk2h %o", back return back; } /** Convert native permissions to DK_PERM_xxx permissions. @param m Native permissions. @return DK_PERM_xxx permissions. */ int dksf_perm_h2dk DK_P1(mode_t, m) { int back = 0; $? "+ dksf_perm_h2dk %o", m #ifdef S_ISUID if(m & S_ISUID) back |= DK_PERM_SUID; #else #ifdef _S_ISUID if(m & _S_ISUID) back |= DK_PERM_SUID; #else if(m & DK_PERM_SUID) back |= DK_PERM_SUID; #endif #endif #ifdef S_ISGID if(m & S_ISGID) back |= DK_PERM_SGID; #else #ifdef _S_ISGID if(m & _S_ISGID) back |= DK_PERM_SGID; #else if(m & DK_PERM_SGID) back |= DK_PERM_SGID; #endif #endif #ifdef S_ISVTX if(m & S_ISVTX) back |= DK_PERM_VTX; #else #ifdef _S_ISVTX if(m & _S_ISVTX) back |= DK_PERM_VTX; #else if(m & DK_PERM_VTX) back |= DK_PERM_VTX; #endif #endif #ifdef S_IRUSR if(m & S_IRUSR) back |= DK_PERM_U_READ; #else #ifdef _S_IRUSR if(m & _S_IRUSR) back |= DK_PERM_U_READ; #else if(m & DK_PERM_U_READ) back |= DK_PERM_U_READ; #endif #endif #ifdef S_IWUSR if(m & S_IWUSR) back |= DK_PERM_U_WRITE; #else #ifdef _S_IWUSR if(m & _S_IWUSR) back |= DK_PERM_U_WRITE; #else if(m & DK_PERM_U_WRITE) back |= DK_PERM_U_WRITE; #endif #endif #ifdef S_IXUSR if(m & S_IXUSR) back |= DK_PERM_U_EXECUTE; #else #ifdef _S_IXUSR if(m & _S_IXUSR) back |= DK_PERM_U_EXECUTE; #else if(m & DK_PERM_U_EXECUTE) back |= DK_PERM_U_EXECUTE; #endif #endif #ifdef S_IRGRP if(m & S_IRGRP) back |= DK_PERM_G_READ; #else #ifdef _S_IRGRP if(m & _S_IRGRP) back |= DK_PERM_G_READ; #else if(m & DK_PERM_G_READ) back |= DK_PERM_G_READ; #endif #endif #ifdef S_IWGRP if(m & S_IWGRP) back |= DK_PERM_G_WRITE; #else #ifdef _S_IWGRP if(m & _S_IWGRP) back |= DK_PERM_G_WRITE; #else if(m & DK_PERM_G_WRITE) back |= DK_PERM_G_WRITE; #endif #endif #ifdef S_IXGRP if(m & S_IXGRP) back |= DK_PERM_G_EXECUTE; #else #ifdef _S_IXGRP if(m & _S_IXGRP) back |= DK_PERM_G_EXECUTE; #else if(m & DK_PERM_G_EXECUTE) back |= DK_PERM_G_EXECUTE; #endif #endif #ifdef S_IROTH if(m & S_IROTH) back |= DK_PERM_O_READ; #else #ifdef _S_IROTH if(m & _S_IROTH) back |= DK_PERM_O_READ; #else if(m & DK_PERM_O_READ) back |= DK_PERM_O_READ; #endif #endif #ifdef S_IWOTH if(m & S_IWOTH) back |= DK_PERM_O_WRITE; #else #ifdef _S_IWOTH if(m & _S_IWOTH) back |= DK_PERM_O_WRITE; #else if(m & DK_PERM_O_WRITE) back |= DK_PERM_O_WRITE; #endif #endif #ifdef S_IXOTH if(m & S_IXOTH) back |= DK_PERM_O_EXECUTE; #else #ifdef _S_IXOTH if(m & _S_IXOTH) back |= DK_PERM_O_EXECUTE; #else if(m & DK_PERM_O_EXECUTE) back |= DK_PERM_O_EXECUTE; #endif #endif $? "- dksf_perm_h2dk %o", back return back; } /** Convert timestamp to text. @param s String buffer for result. @param t Timestamp structure. */ static void internal_time_convert DK_P2(char *, s, struct tm *, t) { struct tm *tm; $? "+ dksf_time_convert %lx", t tm = t; s[0] = '\0'; sprintf(s, time_format, (tm->tm_year + 1900), (tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec ); $? "- dksf_time_convert %s", TR_STR(s) } void dksf_time_convert DK_P2(char *, s, time_t, t) { struct tm *tm; $? "+ dksf_time_convert %lx", t tm = localtime(&t); s[0] = '\0'; if(tm) { internal_time_convert(s, tm); } $? "- dksf_time_convert %s", TR_STR(s) } /** Initialize a struct tm. @param tm Struct to initialize. */ static void init_struct_tm DK_P1(struct tm *,tm) { tm->tm_sec = 0; tm->tm_min = 0; tm->tm_hour = 0; tm->tm_mday = 1; tm->tm_mon = 0; tm->tm_year = 0; tm->tm_wday = 0; tm->tm_yday = 0; tm->tm_isdst = 0; } /** Initialize a dk_stat_t structure. @param ptr Structure to inspect. */ static void dkstat_init DK_P1(dk_stat_t, *ptr) { $? "= dkstat_init %s", TR_PTR(ptr) ptr->permissions = 0; ptr->filetype = 0; #if DK_HAVE_LONG_LONG_INT ptr->size = 0ULL; $? ". have long long" #else ptr->size = 0UL; $? ". no long long" #endif ptr->size_math_error = 0; ptr->inode_number = 0UL; ptr->device_number = 0UL; ptr->rdevice_number = 0UL; ptr->number_of_links = 0UL; ptr->uid = 0L; ptr->gid = 0L; ptr->ctime[0] = ptr->atime[0] = ptr->mtime[0] = '\0'; ptr->is_far_link = 0; /* ptr->ori_ctime = ptr->ori_atime = ptr->ori_mtime = (time_t)0L; */ init_struct_tm(&(ptr->ori_ctime)); init_struct_tm(&(ptr->ori_atime)); init_struct_tm(&(ptr->ori_mtime)); ptr->ud = 0x00; ptr->gd = 0x00; } int dkstat_get DK_P2(dk_stat_t *, ptr, char *, filename) { int back = 0; struct tm *tm; $? "+ dkstat_get %s %s", TR_PTR(ptr), TR_STR(filename) if((ptr) && (filename)) { #if defined(WIN32) || defined(_WIN32) #if DK_HAVE__STAT64 /* + _stat64 */ struct __stat64 st; #if DK_HAVE__LSTAT64 struct __stat64 lst; #endif if(_stat64(filename, &st) == 0) { back = 1; ptr->filetype = dksf_filetype(st.st_mode); ptr->permissions = dksf_perm_h2dk(st.st_mode); ptr->inode_number = (unsigned long)(st.st_ino); ptr->device_number = (unsigned long)(st.st_dev); ptr->rdevice_number = (unsigned long)(st.st_rdev); ptr->size = (dk_long_long_unsigned_t)(st.st_size); $? ". off_t=%lu dk_long_long_t=%lu", ((unsigned long)sizeof(off_t)), ((unsigned long)sizeof(dk_long_long_unsigned_t)) if(sizeof(off_t)>sizeof(dk_long_long_unsigned_t)) { ptr->size_math_error = (((off_t)(ptr->size) != st.st_size) ? 1 : 0); } else { ptr->size_math_error = 0; $? ". sizeof(off_t) <= sizeof(dk_long_long_unsigned_t) -> error=0" } ptr->number_of_links = (unsigned long)(st.st_nlink); ptr->uid = (long)(st.st_uid); ptr->gid = (long)(st.st_gid); ptr->ctime[0] = '\0'; ptr->atime[0] = '\0'; ptr->mtime[0] = '\0'; /* ptr->ori_ctime = st.st_ctime; ptr->ori_atime = st.st_atime; ptr->ori_mtime = st.st_mtime; */ tm = _localtime64(&(st.st_ctime)); if(tm) { DK_MEMCPY(&(ptr->ori_ctime), tm, sizeof(STRUCTTM)); } tm = _localtime64(&(st.st_atime)); if(tm) { DK_MEMCPY(&(ptr->ori_atime), tm, sizeof(STRUCTTM)); } tm = _localtime64(&(st.st_mtime)); if(tm) { DK_MEMCPY(&(ptr->ori_mtime), tm, sizeof(STRUCTTM)); } #if DK_HAVE__LSTAT64 if(_lstat64(filename, &lst) == 0) { $? ". lstat ok" if(dksf_filetype(lst.st_mode) == DK_FT_SYMLINK) { $? ". have symlink" ptr->filetype |= DK_FT_SYMLINK; if(lst.st_dev != st.st_dev) { ptr->is_far_link = 1; } } if(st.st_uid != lst.st_uid) { ptr->ud = 0x01; } if(st.st_gid != lst.st_gid) { ptr->gd = 0x01; } } else { $? "! lstat failed" back = 0; } #endif } /* - _stat64 */ #else /* if DK_HAVE__STAT64 */ #if DK_HAVE__STAT32 /* + _stat32 */ struct __stat32 st; #if DK_HAVE__LSTAT32 struct __stat32 lst; #endif if(_stat32(filename, &st) == 0) { back = 1; ptr->filetype = dksf_filetype(st.st_mode); ptr->permissions = dksf_perm_h2dk(st.st_mode); ptr->inode_number = (unsigned long)(st.st_ino); ptr->device_number = (unsigned long)(st.st_dev); ptr->rdevice_number = (unsigned long)(st.st_rdev); ptr->size = (dk_long_long_unsigned_t)(st.st_size); $? ". off_t=%lu dk_long_long_t=%lu", ((unsigned long)sizeof(off_t)), ((unsigned long)sizeof(dk_long_long_unsigned_t)) if(sizeof(off_t)>sizeof(dk_long_long_unsigned_t)) { ptr->size_math_error = (((st.st_size) > ((off_t)DK_MAX_LONG_LONG_UNSIGNED)) ? 1 : 0); $? ". sizeof(off_t) > sizeof(dk_long_long_unsigned_t) -> error=%d", ptr->size_math_error } else { ptr->size_math_error = 0; $? ". sizeof(off_t) <= sizeof(dk_long_long_unsigned_t) -> error=0" } ptr->number_of_links = (unsigned long)(st.st_nlink); ptr->uid = (long)(st.st_uid); ptr->gid = (long)(st.st_gid); ptr->ctime[0] = '\0'; ptr->atime[0] = '\0'; ptr->mtime[0] = '\0'; /* ptr->ori_ctime = st.st_ctime; ptr->ori_atime = st.st_atime; ptr->ori_mtime = st.st_mtime; */ tm = localtime(&(st.st_ctime)); if(tm) { DK_MEMCPY(&(ptr->ori_ctime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_atime)); if(tm) { DK_MEMCPY(&(ptr->ori_atime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_mtime)); if(tm) { DK_MEMCPY(&(ptr->ori_mtime), tm, sizeof(STRUCTTM)); } #if DK_HAVE__LSTAT32 if(_lstat32(filename, &lst) == 0) { $? ". lstat ok" if(dksf_filetype(lst.st_mode) == DK_FT_SYMLINK) { $? ". have symlink" ptr->filetype |= DK_FT_SYMLINK; if(lst.st_dev != st.st_dev) { ptr->is_far_link = 1; } } if(st.st_uid != lst.st_uid) { ptr->ud = 0x01; } if(st.st_gid != lst.st_gid) { ptr->gd = 0x01; } } else { $? "! lstat failed" back = 0; } #endif } /* - _stat32 */ #else /* if DK_HAVE__STAT32 */ #if DK_HAVE__STAT /* + _stat */ struct _stat st; #if DK_HAVE__LSTAT struct _stat lst; #endif if(_stat(filename, &st) == 0) { back = 1; ptr->filetype = dksf_filetype(st.st_mode); ptr->permissions = dksf_perm_h2dk(st.st_mode); ptr->inode_number = (unsigned long)(st.st_ino); ptr->device_number = (unsigned long)(st.st_dev); ptr->rdevice_number = (unsigned long)(st.st_rdev); ptr->size = (dk_long_long_unsigned_t)(st.st_size); $? ". off_t=%lu dk_long_long_t=%lu", ((unsigned long)sizeof(off_t)), ((unsigned long)sizeof(dk_long_long_unsigned_t)) if(sizeof(off_t)>sizeof(dk_long_long_unsigned_t)) { ptr->size_math_error = (((st.st_size) > ((off_t)DK_MAX_LONG_LONG_UNSIGNED)) ? 1 : 0); $? ". sizeof(off_t) > sizeof(dk_long_long_unsigned_t) -> error=%d", ptr->size_math_error } else { ptr->size_math_error = 0; $? ". sizeof(off_t) <= sizeof(dk_long_long_unsigned_t) -> error=0" } ptr->number_of_links = (unsigned long)(st.st_nlink); ptr->uid = (long)(st.st_uid); ptr->gid = (long)(st.st_gid); ptr->ctime[0] = '\0'; ptr->atime[0] = '\0'; ptr->mtime[0] = '\0'; /* ptr->ori_ctime = st.st_ctime; ptr->ori_atime = st.st_atime; ptr->ori_mtime = st.st_mtime; */ tm = localtime(&(st.st_ctime)); if(tm) { DK_MEMCPY(&(ptr->ori_ctime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_atime)); if(tm) { DK_MEMCPY(&(ptr->ori_atime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_mtime)); if(tm) { DK_MEMCPY(&(ptr->ori_mtime), tm, sizeof(STRUCTTM)); } #if DK_HAVE__LSTAT if(_lstat(filename, &lst) == 0) { $? ". lstat ok" if(dksf_filetype(lst.st_mode) == DK_FT_SYMLINK) { $? ". have symlink" ptr->filetype |= DK_FT_SYMLINK; if(lst.st_dev != st.st_dev) { ptr->is_far_link = 1; } } if(st.st_uid != lst.st_uid) { ptr->ud = 0x01; } if(st.st_gid != lst.st_gid) { ptr->gd = 0x01; } } else { $? "! lstat failed" back = 0; } #endif } /* - _stat */ #else /* if DK_HAVE__STAT*/ /* Problem */ #endif /* if DK_HAVE__STAT*/ #endif /* if DK_HAVE__STAT32 */ #endif /* if DK_HAVE__STAT64 */ #else /* if defined(WIN32) || defined(_WIN32) */ #if DK_HAVE_STAT64 && DK_HAVE_LARGEFILE64_SOURCE /* + stat64 */ struct stat64 st; #if DK_HAVE_LSTAT64 struct stat64 lst; #endif if(stat64(filename, &st) == 0) { back = 1; ptr->filetype = dksf_filetype(st.st_mode); ptr->permissions = dksf_perm_h2dk(st.st_mode); ptr->inode_number = (unsigned long)(st.st_ino); ptr->device_number = (unsigned long)(st.st_dev); ptr->rdevice_number = (unsigned long)(st.st_rdev); ptr->size = (dk_long_long_unsigned_t)(st.st_size); if(sizeof(off_t)>sizeof(dk_long_long_unsigned_t)) { ptr->size_math_error = (((st.st_size) > ((off_t)DK_MAX_LONG_LONG_UNSIGNED)) ? 1 : 0); $? ". sizeof(off_t) > sizeof(dk_long_long_unsigned_t) -> error=%d", ptr->size_math_error } else { ptr->size_math_error = 0; $? ". sizeof(off_t) <= sizeof(dk_long_long_unsigned_t) -> error=0" } ptr->number_of_links = (unsigned long)(st.st_nlink); ptr->uid = (long)(st.st_uid); ptr->gid = (long)(st.st_gid); ptr->ctime[0] = '\0'; ptr->atime[0] = '\0'; ptr->mtime[0] = '\0'; tm = localtime(&(st.st_ctime)); if(tm) { DK_MEMCPY(&(ptr->ori_ctime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_atime)); if(tm) { DK_MEMCPY(&(ptr->ori_atime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_mtime)); if(tm) { DK_MEMCPY(&(ptr->ori_mtime), tm, sizeof(STRUCTTM)); } #if DK_HAVE_LSTAT64 if(lstat64(filename, &lst) == 0) { if(dksf_filetype(lst.st_mode) == DK_FT_SYMLINK) { $? ". have symlink" ptr->filetype |= DK_FT_SYMLINK; if(lst.st_dev != st.st_dev) { ptr->is_far_link = 1; } } if(st.st_uid != lst.st_uid) { ptr->ud = 0x01; } if(st.st_gid != lst.st_gid) { ptr->gd = 0x01; } } else { back = 0; } #endif } /* - stat64 */ #else /* if DK_HAVE_STAT64 */ #if DK_HAVE_STAT /* + stat */ struct stat st; #if DK_HAVE_LSTAT struct stat lst; #endif if(stat(filename, &st) == 0) { back = 1; ptr->filetype = dksf_filetype(st.st_mode); ptr->permissions = dksf_perm_h2dk(st.st_mode); ptr->inode_number = (unsigned long)(st.st_ino); ptr->device_number = (unsigned long)(st.st_dev); ptr->rdevice_number = (unsigned long)(st.st_rdev); ptr->size = (dk_long_long_unsigned_t)(st.st_size); $? ". off_t=%lu dk_long_long_t=%lu", ((unsigned long)sizeof(off_t)), ((unsigned long)sizeof(dk_long_long_unsigned_t)) if(sizeof(off_t)>sizeof(dk_long_long_unsigned_t)) { ptr->size_math_error = (((st.st_size) > ((off_t)DK_MAX_LONG_LONG_UNSIGNED)) ? 1 : 0); $? ". sizeof(off_t) > sizeof(dk_long_long_unsigned_t) -> error=%d", ptr->size_math_error } else { ptr->size_math_error = 0; $? ". sizeof(off_t) <= sizeof(dk_long_long_unsigned_t) -> error=0" } ptr->number_of_links = (unsigned long)(st.st_nlink); ptr->uid = (long)(st.st_uid); ptr->gid = (long)(st.st_gid); ptr->ctime[0] = '\0'; ptr->atime[0] = '\0'; ptr->mtime[0] = '\0'; /* ptr->ori_ctime = st.st_ctime; ptr->ori_atime = st.st_atime; ptr->ori_mtime = st.st_mtime; */ tm = localtime(&(st.st_ctime)); if(tm) { DK_MEMCPY(&(ptr->ori_ctime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_atime)); if(tm) { DK_MEMCPY(&(ptr->ori_atime), tm, sizeof(STRUCTTM)); } tm = localtime(&(st.st_mtime)); if(tm) { DK_MEMCPY(&(ptr->ori_mtime), tm, sizeof(STRUCTTM)); } #if DK_HAVE_LSTAT if(lstat(filename, &lst) == 0) { $? ". lstat ok" if(dksf_filetype(lst.st_mode) == DK_FT_SYMLINK) { $? ". have symlink" ptr->filetype |= DK_FT_SYMLINK; if(lst.st_dev != st.st_dev) { ptr->is_far_link = 1; } } if(st.st_uid != lst.st_uid) { ptr->ud = 0x01; } if(st.st_gid != lst.st_gid) { ptr->gd = 0x01; } } else { $? "! lstat failed" back = 0; } #endif } /* - stat */ #else /* if DK_HAVE_STAT */ /* Problem */ #endif /* if DK_HAVE_STAT */ #endif /* if DK_HAVE_STAT64 */ #endif /* if defined(WIN32) || defined(_WIN32) */ } $? "- dkstat_get %d", back return back; } int dksf_must_rebuild DK_P2(char *,d, char *,s) { int back = 0; if((d) && (s)) { #if defined(WIN32) || defined(_WIN32) #if DK_HAVE__STAT64 struct __stat64 sst, dst; if(_stat64(s, &sst) == 0) { back = 1; if(_stat64(d, &dst) == 0) { if(dst.st_mtime > sst.st_mtime) { back = 0; } } } #else #if DK_HAVE__STAT32 struct __stat32 sst, dst; if(_stat32(s, &sst) == 0) { back = 1; if(_stat32(d, &dst) == 0) { if(dst.st_mtime > sst.st_mtime) { back = 0; } } } #else struct _stat sst, dst; if(_stat(s, &sst) == 0) { back = 1; if(_stat(d, &dst) == 0) { if(dst.st_mtime > sst.st_mtime) { back = 0; } } } #endif #endif #else #if DK_HAVE_STAT64 && DK_HAVE_LARGEFILE64_SOURCE struct stat64 sst, dst; if(stat64(s, &sst) == 0) { back = 1; if(stat64(d, &dst) == 0) { if(dst.st_mtime > sst.st_mtime) { back = 0; } } } #else #if DK_HAVE_STAT struct stat sst, dst; if(stat(s, &sst) == 0) { back = 1; /* have source */ if(stat(d, &dst) == 0) { if(dst.st_mtime > sst.st_mtime) { back = 0; /* up to date */ } } } #endif #endif #endif } return back; } int dkstat_far_link DK_P1(dk_stat_t *, ptr) { int back = 0; if(ptr) { back = ptr->is_far_link; } return back; } dk_stat_t * dkstat_open DK_P1(char *, filename) { dk_stat_t *back = NULL; $? "+ dkstat_open %s", TR_STR(filename) if(filename) { back = dk_new(dk_stat_t,1); if(back) { dkstat_init(back); if(!dkstat_get(back,filename)) { dk_delete(back); back = NULL; } } } $? "- dkstat_open %s", TR_PTR(back) return back; } void dkstat_close DK_P1(dk_stat_t *, ptr) { $? "= dkstat_close %s", TR_PTR(ptr) if(ptr) { dk_delete(ptr); } } int dkstat_filetype DK_P1(dk_stat_t *, ptr) { int back = 0; $? "+ dkstat_filetype %s", TR_PTR(ptr) if(ptr) back = ptr->filetype; $? "- dkstat_filetype %d", back return back; } int dkstat_permissions DK_P1(dk_stat_t *, ptr) { int back = 0; $? "+ dkstat_permissions %s", TR_PTR(ptr) if(ptr) back = ptr->permissions; $? "- dkstat_permissions %o", back return back; } unsigned long dkstat_inode DK_P1(dk_stat_t *, ptr) { unsigned long back = 0UL; if(ptr) back = ptr->inode_number; $? "= dkstat_inode %s %lu", TR_PTR(ptr), back return back; } unsigned long dkstat_device DK_P1(dk_stat_t *, ptr) { unsigned long back = 0UL; if(ptr) back = ptr->device_number; $? "= dkstat_device %s, %lu", TR_PTR(ptr), back return back; } unsigned long dkstat_rdevice DK_P1(dk_stat_t *, ptr) { unsigned long back = 0UL; if(ptr) back = ptr->rdevice_number; $? "= dkstat_rdevice %s %lu", TR_PTR(ptr), back return back; } unsigned long dkstat_nlinks DK_P1(dk_stat_t *, ptr) { unsigned long back = 0UL; if(ptr) back = ptr->number_of_links; $? "= dkstat_nlinks %s %lu", TR_PTR(ptr), back return back; } dk_long_long_unsigned_t dkstat_size DK_P1(dk_stat_t *, ptr) { #if DK_HAVE_LONG_LONG_INT dk_long_long_unsigned_t back = 0ULL; #else dk_long_long_unsigned_t back = 0UL; #endif if(ptr) back = ptr->size; #if DK_HAVE_LONG_LONG_INT $? "= dkstat_size %s %llu", TR_PTR(ptr), back #else $? "= dkstat_size %s %lu", TR_PTR(ptr), back #endif return back; } dk_long_long_unsigned_t dkstat_size_ok DK_P2(dk_stat_t *, ptr, int *,ok) { #if DK_HAVE_LONG_LONG_INT dk_long_long_unsigned_t back = 0ULL; #else dk_long_long_unsigned_t back = 0UL; #endif if(ptr) { back = ptr->size; if(ptr->size_math_error) { if(ok) { *ok = DK_ERR_MATH_OOR; } } } #if DK_HAVE_LONG_LONG_INT $? "= dkstat_size %s %llu", TR_PTR(ptr), back #else $? "= dkstat_size %s %lu", TR_PTR(ptr), back #endif return back; } long dkstat_uid DK_P1(dk_stat_t *, ptr) { long back = -1; if(ptr) back = ptr->uid; $? "= dkstat_uid %s %ld", TR_PTR(ptr), back return back; } long dkstat_gid DK_P1(dk_stat_t *, ptr) { long back = -1; if(ptr) back = ptr->gid; $? "= dkstat_gid %s %ld", TR_PTR(ptr), back return back; } char * dkstat_ctime DK_P1(dk_stat_t *, ptr) { char *back = NULL; if(ptr) { back = &(ptr->ctime[0]); if(!(*back)) { internal_time_convert(back, &(ptr->ori_ctime)); } } $? "= dkstat_ctime %s %s", TR_PTR(ptr), TR_STR(back) return back; } char * dkstat_atime DK_P1(dk_stat_t *, ptr) { char *back = NULL; if(ptr) { back = &(ptr->atime[0]); if(!(*back)) { internal_time_convert(back, &(ptr->ori_atime)); } } $? "= dkstat_atime %s %s", TR_PTR(ptr), TR_STR(back) return back; } char * dkstat_mtime DK_P1(dk_stat_t *, ptr) { char *back = NULL; if(ptr) { back = &(ptr->mtime[0]); if(!(*back)) { internal_time_convert(back, &(ptr->ori_mtime)); } } $? "= dkstat_mtime %s %s", TR_PTR(ptr), TR_STR(back) return back; } int dksf_mkdir DK_P2(char *, path, int, mode) { int back = 0; mode_t mode_translated; $? "+ dksf_mkdir %s %o", TR_STR(path), mode if(path) { mode_translated = dksf_perm_dk2h(mode); #if DK_HAVE_MKDIR2 if(mkdir(path, mode_translated) == 0) { back = 1; } #else #if DK_HAVE_MKDIR || DK_HAVE__MKDIR #if DK_HAVE_MKDIR if(mkdir(path) == 0) { #else if(_mkdir(path) == 0) { #endif back = 1; } #endif #endif } $? "- dksf_mkdir %d %d", back, errno return back; } int dksf_chmod DK_P2(char *, path, int, mode) { int back = 0; $? "+ dksf_chmod %s %d", TR_STR(path), mode if(path) { #if DK_HAVE_CHMOD mode_t mode_translated; mode_translated = dksf_perm_dk2h(mode); if(chmod(path, mode_translated) == 0) { back = 1; } #endif } $? "- dksf_chmod %d", back return back; } int dksf_fchmod DK_P2(int,fd, int,mode) { int back = 0; #if DK_HAVE_FCHMOD mode_t mode_translated; mode_translated = dksf_perm_dk2h(mode); if(fchmod(fd, mode_translated) == 0) { back = 1; } #endif return back; } dk_stat_t * dkstat_new DK_P0() { dk_stat_t *back = NULL; $? "+ dkstat_new" back = dk_new(dk_stat_t,1); if(back) { dkstat_init(back); } $? "- dkstat_new %s", TR_PTR(back) return back; } void dkstat_delete DK_P1(dk_stat_t *, ptr) { $? "= dkstat_delete %s", TR_PTR(ptr) if(ptr) { dk_delete(ptr); } } long dksf_getpid DK_P0() { long back = -1L; #if DK_HAVE_GETCURRENTPROCESSID back = GetCurrentProcessId(); #else #if DK_HAVE_GETPID back = (long)getpid(); #endif #endif $? "= dksf_getpid %ld", back return back; } int dksf_have_getpid DK_P0() { int back = 0; #if DK_HAVE_GETPID back = 1; #endif $? "= dksf_have_getpid %d", back return back; } long dksf_getppid DK_P0() { long back = -1L; #if DK_HAVE_GETPPID back = (long)getppid(); #else back = dksf_getpid(); #endif $? "= dksf_getppid %ld", back return back; } int dksf_have_getppid DK_P0() { int back = 0; #if DK_HAVE_GETPPID back = 1; #endif $? "= dksf_have_getppid %d", back return back; } long dksf_getuid DK_P0() { long back = -1L; #if DK_HAVE_GETUID back = (long)getuid(); #endif $? "= dksf_getuid %ld", back return back; } int dksf_have_getuid DK_P0() { int back = 0; #if DK_HAVE_GETUID back = 1; #endif $? "= dksf_have_getuid %d", back return back; } long dksf_getgid DK_P0() { long back = -1L; #if DK_HAVE_GETGID back = (long)getgid(); #endif $? "= dksf_getgid %ld", back return back; } int dksf_have_getgid DK_P0() { int back = 0; #if DK_HAVE_GETGID back = 1; #endif $? "= dksf_have_getgid %d", back return back; } long dksf_geteuid DK_P0() { long back = -1L; #if DK_HAVE_GETEUID back = (long)geteuid(); #endif $? "= dksf_geteuid %ld", back return back; } int dksf_have_geteuid DK_P0() { int back = 0; #if DK_HAVE_GETEUID back = 1; #endif $? "= dksf_have_geteuid %d", back return back; } long dksf_getegid DK_P0() { long back = -1L; #if DK_HAVE_GETEGID back = (long)getegid(); #endif $? "= dksf_getegid %ld", back return back; } int dksf_have_getegid DK_P0() { int back = 0; #if DK_HAVE_GETEGID back = 1; #endif $? "= dksf_have_getegid %d", back return back; } long dksf_getpgrp DK_P0() { long back = -1L; #if DK_HAVE_GETPGRP back = (long)getpgrp(); #endif $? "= dksf_getpgrp %ld", back return back; } int dksf_have_getpgrp DK_P0() { int back = 0; #if DK_HAVE_GETPGRP back = 1; #endif $? "= dksf_have_getpgrp %d", back return back; } long dksf_getpgid DK_P1(long, x) { long back = -1L; #if DK_HAVE_GETPGID back = (long)getpgid((pid_t)x); #endif $? "= dksf_getpgid %ld", back return back; } int dksf_have_getpgid DK_P0() { int back = 0; #if DK_HAVE_GETPGID back = 1; #endif $? "= dksf_have_getpgid %d", back return back; } #if DK_HAVE_WINREG_H /** List of registry key and entry names to inspect. */ static char *subkeys_to_inspect[] = { "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "System\\CurrentControlSet\\Services\\Tcpip\\Parameters", "System\\CurrentControlSet\\Control\\ComputerName\\ComputerName", "System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", "DefaultUserName", "Hostname", "Domain", "ComputerName", "System\\CurrentControlSet\\control", "Current User", "Network\\Logon", "username", "System\\CurrentControlSet\\Services\\VxD\\MSTCP", "System\\CurrentControlSet\\Services\\VxD\\VNETSUP", "HostName", NULL }; /** Read a string from the registry. @param dest Result buffer. @param dsz Size of \a dest. @param what Indicator for registry hive and key and entry name. */ static int read_registry_string DK_P3(char *, dest, size_t, dsz, int, what) { int back = 0; char *subkey, *entry_key; $? "+ read_registry_string %d", what subkey = entry_key = NULL; switch(what) { case 0: { subkey = subkeys_to_inspect[0]; entry_key = subkeys_to_inspect[4]; } break; case 1: { subkey = subkeys_to_inspect[1]; entry_key = subkeys_to_inspect[5]; } break; case 2: { subkey = subkeys_to_inspect[1]; entry_key = subkeys_to_inspect[6]; } break; case 3: { subkey = subkeys_to_inspect[3]; entry_key = subkeys_to_inspect[7]; } break; case 4: { subkey = subkeys_to_inspect[2]; entry_key = subkeys_to_inspect[7]; } break; case 5: { /* HKLM/System/CurrentControlSet/control:Current User */ subkey = subkeys_to_inspect[8]; entry_key = subkeys_to_inspect[9]; } break; case 6: { /* HKLM/Network/Logon:username */ subkey = subkeys_to_inspect[10]; entry_key = subkeys_to_inspect[11]; } break; case 7: { /* HKLM/System/CurrentControlSet/Services/VxD/MSTCP:HostName */ subkey = subkeys_to_inspect[12]; entry_key = subkeys_to_inspect[14]; } break; case 8: { /* HKLM/System/CurrentControlSet/Services/VxD/VNETSUP:ComputerName */ subkey = subkeys_to_inspect[13]; entry_key = subkeys_to_inspect[7]; } break; case 9: { subkey = subkeys_to_inspect[12]; entry_key = subkeys_to_inspect[6]; } break; } $? ". subkey = %s, entry_key = %s", TR_STR(subkey), TR_STR(entry_key) if(subkey && entry_key) { HKEY hklmsl; PHKEY phkSubkey; DWORD disp, dwType, sz; LONG retval; phkSubkey = &hklmsl; retval = RegCreateKeyExA( HKEY_LOCAL_MACHINE, subkey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE, NULL, phkSubkey, &disp ); if(retval == ERROR_SUCCESS) { $? ". registry hive geoeffnet" sz = dsz; retval = RegQueryValueExA( hklmsl, entry_key, NULL, &dwType, dest, &sz ); if(retval == ERROR_SUCCESS) { $? ". Eintrag gefunden" if(sz < dsz) { $? ". Laenge des Eintrages ok" dest[sz] = '\0'; back = 1; } } else { $? "! Eintrag nicht gefunden" } } else { $? "! Fehler beim Oeffnen der Registry" } } $? "- read_registry_string %d", back return back; } #endif #if DK_HAVE_GETPWUID || DK_HAVE_GETPWENT /** Save information to buffer. @param buffer Result buffer. @param sz Size of \a buffer. @param who 0=UID, 1=effective UID. @param how 0=LOGNAME, 1=HOME. @return 1 on success, 0 on error. */ static int fill_buffer DK_P4(char *, buffer, size_t, sz, int, who, int, how) { int back = 0; #if DK_HAVE_GETUID uid_t uid; struct passwd *pw; #if !DK_HAVE_SETPWENT struct passwd *xpw; #endif #if DK_HAVE_GETEUID uid = (who ? getuid() : geteuid()); #else uid = getuid(); #endif #if DK_HAVE_GETPWUID pw = getpwuid(uid); #else pw = NULL; #if DK_HAVE_SETPWENT setpwent(); #endif xpw = getpwent(); while((!pw) & (xpw)) { if(xpw->pw->uid == uid) { pw = xpw; } if(!pw) { xpw = getpwent(); } } #endif switch(how) { case 1: { /* HOME */ if(pw->pw_dir) { if(strlen(pw->pw_dir) < sz) { back = 1; strcpy(buffer, pw->pw_dir); } } } break; case 0: { /* LOGNAME */ if(pw->pw_name) { if(strlen(pw->pw_name) < sz) { back = 1; strcpy(buffer, pw->pw_name); } } } break; } #if (!DK_HAVE_GETPWUID) && DK_HAVE_GETENDPWENT endpwent(); #endif #else /* So what */ #endif $? "= fill_buffer %d", back return back; } #endif int dksf_get_uname DK_P2(char *, buffer, size_t, sz) { int back = 0; $? "+ dksf_get_uname %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { #if DK_HAVE_GETPWUID || DK_HAVE_GETPWENT back = fill_buffer(buffer, sz, 1, 0); #else char *x; #if DK_HAVE_GETUSERNAME DWORD xs; xs = sz; if(GetUserNameA(buffer,&xs)) { back = 1; if(xs >= sz) { xs--; } buffer[(size_t)xs] = '\0'; } #endif #if DK_HAVE_WINREG_H /* Windows NT 4.0 Workstation */ if(!back) { back = read_registry_string(buffer,sz,0); } if(!back) { back = read_registry_string(buffer,sz,6); } if(!back) { back = read_registry_string(buffer,sz,5); } #endif if(!back) { x = getenv("LOGNAME"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer, x); } } } if(!back) { x = getenv("USERNAME"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer, x); } } } #endif } } $? "- dksf_get_uname %d", back return back; } int dksf_get_euname DK_P2(char *, buffer, size_t, sz) { int back = 0; $? "+ dksf_get_euname %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { #if DK_HAVE_GETPWUID || DK_HAVE_GETPWENT back = fill_buffer(buffer, sz, 0, 0); #else char *x; #if DK_HAVE_GETUSERNAME DWORD xs; xs = sz; if(GetUserNameA(buffer,&xs)) { back = 1; if(xs >= sz) { xs--; } buffer[(size_t)xs] = '\0'; } #endif #if DK_HAVE_WINREG_H back = read_registry_string(buffer,sz,0); #endif if(!back) { x = getenv("LOGNAME"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer, x); } } } if(!back) { x = getenv("USERNAME"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer, x); } } } #endif } } $? "- dksf_get_euname %d", back return back; } #if !(DK_HAVE_GETPWUID || DK_HAVE_GETPWENT) /** Attempt to construct home directory name from environment variables. @param buffer Result buffer. @param sz Size of \a buffer. @return 1 on success, 0 on error. */ static int try_home_from_env DK_P2(char *, buffer, size_t, sz) { int back = 0; char *x; #if DK_HAVE_FEATURE_BACKSLASH char *y; #endif x = getenv("HOME"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer,x); } } if(!back) { #if DK_HAVE_FEATURE_BACKSLASH x = getenv("USERPROFILE"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer,x); } } #endif } if(!back) { #if DK_HAVE_FEATURE_BACKSLASH x = getenv("HOMEDRIVE"); y = getenv("HOMEPATH"); if(x && y) { if((strlen(x) + strlen(y) + strlen(path_component_separator)) < sz) { back = 1; strcpy(buffer,x); if(y[0] != path_component_separator[0]) { strcat(buffer, path_component_separator); } strcat(buffer,y); } } #endif } return back; } #endif /** Get home directory. @param buffer Result buffer. @param sz Size of \a buffer. @return 1 on success, 0 on error. */ static int internal_get_home DK_P2(char *, buffer, size_t, sz) { int back = 0; $? "+ dksf_get_home %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { #if DK_HAVE_GETPWUID || DK_HAVE_GETPWENT back = fill_buffer(buffer, sz, 1, 1); #else back = try_home_from_env(buffer,sz); #endif } } $? "- dksf_get_home %d", back return back; } /** Check permissions to temporary directory. @param buffer Result buffer. @param sz Size of \a buffer. @param x Candidate for temprary directory. @return 1 on success, 0 on error. */ static int check_temp_dir DK_P3(char *, buffer, size_t, sz, char *, x) { int back = 0; dk_stat_t st; $? "+ check_temp_dir %s %lu %s", TR_PTR(buffer), sz, TR_STR(x) if(dkstat_get(&st,x)) { int ft; $? ". stat ok" ft = dkstat_filetype(&st); ft &= (~DK_FT_SYMLINK); if(ft == DK_FT_DIR) { if(strlen(x) < sz) { back = 1; /* strcpy(buffer,x); */ } } } if(!back) { (void)dksf_mkdir(x, DK_PERM_CREATE_DIR); } if(dkstat_get(&st,x)) { int ft; ft = dkstat_filetype(&st); ft &= (~DK_FT_SYMLINK); if(ft == DK_FT_DIR) { if(strlen(x) < sz) { back = 1; /* strcpy(buffer,x); */ } } } $? "- check_temp_dir %d", back return back; } /** Environment variables to inspect for temporary files directory. */ static char *variables_to_check[] = { "TMPDIR", "TEMP", "TMP", NULL }; /** Find temporary directory. @param buffer Buffer for result. @param sz Size of \a buffer. @return 1 on success, 0 on error. */ static int internal_get_tempdir DK_P2(char *, buffer, size_t, sz) { int back = 0; $? "+ dksf_get_tempdir %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { char c, *p1, *p2, *p3, *vptr, **kptr; kptr = variables_to_check; while((*kptr) && (!back)) { vptr = getenv(*kptr); if(vptr) { if(strlen(vptr) < sz) { strcpy(buffer, vptr); if(dkstr_chr(buffer, ';')) { p1 = buffer; while((p1) && (!back)) { p2 = dkstr_chr(p1, ';'); if(p2) { *(p2++) = '\0'; } back = check_temp_dir(buffer, sz, p1); if(back) { p3 = buffer; while(*p1) { c = *(p1++); *(p3++) = c; } *p3 = '\0'; } p1 = p2; } } else { back = check_temp_dir(buffer, sz, vptr); if(back) { strcpy(buffer, vptr); } } } } kptr++; } #if DK_HAVE_FEATURE_BACKSLASH if(!back) { char *x; x = getenv("SystemDrive"); if(x) { if((strlen(x) + strlen(temp_string)) < sz) { strcpy(buffer,x); strcat(buffer,temp_string); back = check_temp_dir(buffer,sz,buffer); } } if(!back) { x = getenv("SystemRoot"); if(x) { if((strlen(x) + strlen(temp_string)) < sz) { strcpy(buffer,x); strcat(buffer,temp_string); back = check_temp_dir(buffer,sz,buffer); } } } if(!back) { x = getenv("windir"); if(x) { if((strlen(x) + strlen(temp_string)) < sz) { strcpy(buffer,x); strcat(buffer,temp_string); back = check_temp_dir(buffer,sz,buffer); } } } } #endif } } $? "- dksf_get_tempdir %d", back return back; } int dksf_get_ehome DK_P2(char *, buffer, size_t, sz) { int back = 0; $? "+ dksf_get_ehome %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { #if DK_HAVE_GETPWUID || DK_HAVE_GETPWENT back = fill_buffer(buffer, sz, 0, 1); #else back = try_home_from_env(buffer,sz); #endif if(!back) { back = internal_get_tempdir(buffer,sz); } } } $? "- dksf_get_ehome %d", back return back; } int dksf_get_hostname DK_P2(char *, buffer, size_t, sz) { int back = 0; #if DK_HAVE_GETCOMPUTERNAME size_t xs; #endif $? "+ dksf_get_hostname %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { #if DK_HAVE_SYS_SYSTEMINFO #if DK_HAVE_SYSINFO #ifdef SI_HOSTNAME long l; l = sysinfo(SI_HOSTNAME, buffer, sz); if((l > 0L) && (l <= sz)) { back = 1; } #endif #endif #endif #if DK_HAVE_GETCOMPUTERNAME xs = sz; if(!back) { if(GetComputerNameA(buffer,&xs)) { if(xs >= sz) { xs--; } buffer[(size_t)xs] = '\0'; back = 1; } } #endif #if DK_HAVE_GETHOSTNAME if(!back) { if(gethostname(buffer, (int)sz) == 0) { back = 1; buffer[(sz-1UL)] = '\0'; } } #endif if(!back) { #if DK_HAVE_WINREG_H /* Windows NT 4.0 Workstation */ back = read_registry_string(buffer,sz,1); if(!back) { back = read_registry_string(buffer,sz,3); } if(!back) { back = read_registry_string(buffer,sz,4); } /* Windows 95 */ if(!back) { back = read_registry_string(buffer,sz,7); } if(!back) { back = read_registry_string(buffer,sz,8); } #endif } if(!back) { char *x; x = getenv("COMPUTERNAME"); if(x) { if(strlen(x) < sz) { back = 1; strcpy(buffer,x); } } } } } $? "- dksf_get_hostname %d", back return back; } int dksf_get_home DK_P2(char *, buffer, size_t, sz) { int back; back = internal_get_home(buffer,sz); if(!back) { back = internal_get_tempdir(buffer,sz); } return back; } int dksf_get_tempdir DK_P2(char *, buffer, size_t, sz) { int back; back = internal_get_tempdir(buffer,sz); if(!back) { back = internal_get_home(buffer,sz); } return back; } int dksf_get_domainname DK_P2(char *, buffer, size_t, sz) { int back = 0; $? "+ dksf_get_domainname %s %lu", TR_PTR(buffer), sz if(buffer) { if(sz) { #if DK_HAVE_SYS_SYSTEMINFO_H long l; $? ". DK_HAVE_SYS_SYSTEMINFO_H" #if DK_HAVE_SYSINFO $? ". DK_HAVE_SYSINFO" #ifdef SI_SYSNAME $? ". SI_SYSNAME" l = sysinfo(SI_SRPC_DOMAIN, buffer, sz); if((l > 0L) && (l <= sz)) { back = 1; } #else #endif #else #endif #else #endif if(!back) { #if DK_HAVE_WINREG_H /* Windows NT 4.0 Workstation */ back = read_registry_string(buffer,sz,2); /* Windows 95 */ if(!back) { back = read_registry_string(buffer,sz,9); } #endif } } } $? "- dksf_get_domainname %d", back return back; } long dksf_get_maxpathlen DK_P0() { long back = MY_MAXPATHLEN; return back; } long dksf_get_maxfiles DK_P0() { long back = 1024L; #if DK_HAVE_SYS_RESOURCE_H #if DK_HAVE_GETRLIMIT struct rlimit rl; if(getrlimit(RLIMIT_NOFILE, &rl) >= 0) { if(rl.rlim_max != RLIM_INFINITY) { back = (long)(rl.rlim_max); } } #endif #endif return back; } /** Directory state: Not yet initialized. */ #define DIR_STATE_UNUSED 0 /** Directory state: Initialized. */ #define DIR_STATE_INITIALIZED 1 /** Directory state: Opened. */ #define DIR_STATE_OPENED 2 /** Directory state: End of directory reached. */ #define DIR_STATE_WRAPPED 3 /** Directory state: Closed. */ #define DIR_STATE_CLOSED 4 /** Get file properties. @param ptr Directory. @param shortname File name. @return 1 on success, 0 on error. */ static int get_file_properties DK_P2(dk_dir_t *, ptr, char *, shortname) { int back = 0; size_t lgt, lgtx; if((long)strlen(shortname) < ptr->maxpathlen) { strcpy(ptr->shortname, shortname); strcpy(ptr->fullname, ptr->dirname); lgt = lgtx = strlen(ptr->dirname); lgt += strlen(path_component_separator); lgt += strlen(shortname); if((long)lgt < ptr->maxpathlen) { if(((ptr->dirname)[lgtx - 1]) != path_component_separator[0]) { strcat(ptr->fullname, path_component_separator); } strcat(ptr->fullname, shortname); if(dkstat_get(&(ptr->stbuf), ptr->fullname)) { back = 1; } } else { $? "! full name too long" } } else { $? "! name too long" } return back; } int dkdir_start_search DK_P2(dk_dir_t *, ptr, char *, name) { int back = 0; $? "+ dkdir_start_search %s %s", TR_PTR(ptr), TR_STR(name) if((ptr) && (name)) { $? ". arguments ok" switch(ptr->state) { case DIR_STATE_UNUSED: case DIR_STATE_CLOSED: { if((long)strlen(name) < ptr->maxpathlen) { strcpy(ptr->dirname, name); ptr->state = DIR_STATE_INITIALIZED; back = 1; } else { $? "! name too long" } } break; default: { $? "! wrong state" } break; } } else { $? "! arguments" } $? "- dkdir_start_search %d", back return back; } #if defined(WIN32) || defined(_WIN32) /* + Win32 */ #if DK_HAVE__FINDFIRST64 /* Win32, _findfirst64 */ void dkdir_end_search DK_P1(dk_dir_t *,ptr) { $? "+ dkdir_end_search" if(ptr) { switch(ptr->state) { case DIR_STATE_OPENED: case DIR_STATE_WRAPPED: { _findclose(ptr->hFile64); ptr->hFile64 = -1L; } break; default: { $? "! not opened or already closed" } break; } } $? "- dkdir_end_search" } int dkdir_next DK_P1(dk_dir_t *, ptr) { int back = 0; size_t lgt; size_t lgtx; size_t lgty; int i; $? "+ dkdir_next" if(ptr) { switch(ptr->state) { case DIR_STATE_INITIALIZED: { $? ". initialized" lgt = strlen(ptr->dirname); lgtx = lgty = lgt; if(lgt > 0) { lgt += strlen(path_component_separator); lgt += strlen(all_files); if((long)lgt < ptr->maxpathlen) { if(((ptr->dirname)[lgtx - 1]) != path_component_separator[0]) { strcat(ptr->dirname, path_component_separator); } strcat(ptr->dirname, all_files); ptr->hFile64 = _findfirst64(ptr->dirname, &(ptr->fdt64)); (ptr->dirname)[lgtx] = '\0'; if(ptr->hFile64 != -1L) { /* back = get_file_properties(ptr, (ptr->fdt64).name); */ back = 1; if(!get_file_properties(ptr, (ptr->fdt64).name)) { back = -1; } ptr->state = DIR_STATE_OPENED; } else { $? "! findfirst failed" } } else { $? "! dir name too long" } } else { $? "! wrong dir name" } } break; case DIR_STATE_OPENED: { $? ". opened" i = _findnext64(ptr->hFile64, &(ptr->fdt64)); if(i == 0) { /* back = get_file_properties(ptr, (ptr->fdt64).name); */ back = 1; if(!get_file_properties(ptr, (ptr->fdt64).name)) { back = -1; } } else { _findclose(ptr->hFile64); ptr->hFile64 = -1L; ptr->state = DIR_STATE_CLOSED; } } break; default: { $? "! wrong state" } break; } } $? "- dkdir_next %d", back return back; } /** Initialize new directory. @param ptr Directory to initialize. */ static void init_new_directory DK_P1(dk_dir_t *,ptr) { ptr->hFile64 = -1L; } #else #if DK_HAVE__FINDFIRST32 /* Win32, _findfirst32 */ void dkdir_end_search DK_P1(dk_dir_t *,ptr) { $? "+ dkdir_end_search" if(ptr) { switch(ptr->state) { case DIR_STATE_OPENED: case DIR_STATE_WRAPPED: { _findclose(ptr->hFile32); ptr->hFile = -1L; } break; default: { $? "! not opened or already closed" } break; } } $? "- dkdir_end_search" } int dkdir_next DK_P1(dk_dir_t *, ptr) { int back = 0; size_t lgt; size_t lgtx; size_t lgty; $? "+ dkdir_next" if(ptr) { switch(ptr->state) { case DIR_STATE_INITIALIZED: { $? ". initialized" lgt = strlen(ptr->dirname); lgtx = lgty = lgt; if(lgt > 0) { lgt += strlen(path_component_separator); lgt += strlen(all_files); if((long)lgt < ptr->maxpathlen) { if(((ptr->dirname)[lgtx - 1]) != path_component_separator[0]) { strcat(ptr->dirname, path_component_separator); } strcat(ptr->dirname, all_files); ptr->hFile32 = _findfirst32(ptr->dirname, &(ptr->fdt32)); (ptr->dirname)[lgtx] = '\0'; if(ptr->hFile32 != -1L) { /* back = get_file_properties(ptr, (ptr->fdt32).name); */ back = 1; if(!get_file_properties(ptr, (ptr->fdt32).name)) { back = -1; } ptr->state = DIR_STATE_OPENED; } else { $? "! findfirst failed" } } else { $? "! dir name too long" } } else { $? "! wrong dir name" } } break; case DIR_STATE_OPENED: { $? ". opened" i = _findnext32(ptr->hFile32, &(ptr->fdt32)); if(i == 0) { /* back = get_file_properties(ptr, (ptr->fdt32).name); */ back = 1; if(!get_file_properties(ptr, (ptr->fdt32).name)) { back = -1; } } else { _findclose(ptr->hFile32); ptr->hFile32 = -1L; ptr->state = DIR_STATE_CLOSED; } } break; default: { $? "! wrong state" } break; } } $? "- dkdir_next %d", back return back; } /** Initialize new directory. @param ptr Directory to initialize. */ static void init_new_directory DK_P1(dk_dir_t *,ptr) { ptr->hFile32 = -1L; } #else #if DK_HAVE__FINDFIRST /* Win32, _findfirst */ void dkdir_end_search DK_P1(dk_dir_t *,ptr) { $? "+ dkdir_end_search" if(ptr) { switch(ptr->state) { case DIR_STATE_OPENED: case DIR_STATE_WRAPPED: { _findclose(ptr->hFile); ptr->hFile = -1L; } break; default: { $? "! not opened or already closed" } break; } } $? "- dkdir_end_search" } int dkdir_next DK_P1(dk_dir_t *, ptr) { int back = 0; size_t lgt; size_t lgtx; size_t lgty; int i; $? "+ dkdir_next" if(ptr) { switch(ptr->state) { case DIR_STATE_INITIALIZED: { $? ". initialized" lgt = strlen(ptr->dirname); lgtx = lgty = lgt; if(lgt > 0) { lgt += strlen(path_component_separator); lgt += strlen(all_files); if((long)lgt < ptr->maxpathlen) { if(((ptr->dirname)[lgtx - 1]) != path_component_separator[0]) { strcat(ptr->dirname, path_component_separator); } strcat(ptr->dirname, all_files); ptr->hFile = _findfirst(ptr->dirname, &(ptr->fdt)); (ptr->dirname)[lgtx] = '\0'; if(ptr->hFile != -1L) { /* back = get_file_properties(ptr, (ptr->fdt).name); */ back = 1; if(!get_file_properties(ptr, (ptr->fdt).name)) { back = -1; } ptr->state = DIR_STATE_OPENED; } else { $? "! findfirst failed" } } else { $? "! dir name too long" } } else { $? "! wrong dir name" } } break; case DIR_STATE_OPENED: { $? ". opened" i = _findnext(ptr->hFile, &(ptr->fdt)); if(i == 0) { /* back = get_file_properties(ptr, (ptr->fdt).name); */ back = 1; if(!get_file_properties(ptr, (ptr->fdt).name)) { back = -1; } } else { _findclose(ptr->hFile); ptr->hFile = -1L; ptr->state = DIR_STATE_CLOSED; } } break; default: { $? "! wrong state" } break; } } $? "- dkdir_next %d", back return back; } /** Initialize new directory. @param ptr Directory to initialize. */ static void init_new_directory DK_P1(dk_dir_t *,ptr) { ptr->hFile = -1L; } #endif #endif #endif /* - Win32 */ #else #if DK_HAVE_FINDFIRST /* DOS, findfirst */ void dkdir_end_search DK_P1(dk_dir_t *,ptr) { int i; $? "+ dkdir_end_search" if(ptr) { switch(ptr->state) { case DIR_STATE_OPENED: case DIR_STATE_WRAPPED: { i = 0; while(!i) { i = findnext(&(ptr->dir)); } } break; default: { $? "! not opened or already closed" } break; } } $? "- dkdir_end_search" } int dkdir_next DK_P1(dk_dir_t *, ptr) { int back = 0; size_t lgt; size_t lgtx; size_t lgty; int i; $? "+ dkdir_next" if(ptr) { switch(ptr->state) { case DIR_STATE_INITIALIZED: { $? ". initialized" lgt = strlen(ptr->dirname); if(lgt > 0) { lgtx = lgty = lgt; lgt += strlen(all_files); lgt += strlen(path_component_separator); if(lgt < ptr->maxpathlen) { if((ptr->dirname)[lgtx - 1] != path_component_separator[0]) { strcat(ptr->dirname, path_component_separator); } strcat(ptr->dirname, all_files); i = findfirst(ptr->dirname, &(ptr->dir), FA_DIREC); (ptr->dirname)[lgty] = '\0'; if(i == 0) { /* back = get_file_properties(ptr, (ptr->dir).ff_name); */ back = 1; if(!get_file_properties(ptr, (ptr->dir).ff_name)) { back = -1; } ptr->state = DIR_STATE_OPENED; } else { $? "! findfirst failed */ } } else { $? "! name too long" } } else { $? "! wrong name length" } } break; case DIR_STATE_OPENED: { $? ". opened" i = findnext(&(ptr->dir)); if(i == 0) { /* back = get_file_properties(ptr, (ptr->dir).ff_name); */ back = 1; if(!get_file_properties(ptr, (ptr->dir).ff_name)) { back = -1; } } else { ptr->state = DIR_STATE_CLOSED; } } break; default: { $? "! wrong state" } break; } } $? "- dkdir_next %d", back return back; } /** Initialize new directory. @param ptr Directory to initialize. */ static void init_new_directory DK_P1(dk_dir_t *,ptr) { } #else #if DK_HAVE_DIRENT_H /* UNIX/Linux, dirent */ void dkdir_end_search DK_P1(dk_dir_t *,ptr) { $? "+ dkdir_end_search" if(ptr) { switch(ptr->state) { case DIR_STATE_OPENED: case DIR_STATE_WRAPPED: { closedir(ptr->dir); ptr->dir = NULL; $? ". closing dir" ptr->state = DIR_STATE_CLOSED; } break; default: { $? "! not opened or already closed" } break; } } $? "- dkdir_end_search" } int dkdir_next DK_P1(dk_dir_t *, ptr) { int back = 0; struct dirent *de; $? "+ dkdir_next" if(ptr) { switch(ptr->state) { case DIR_STATE_INITIALIZED: { $? ". initialized" if(strlen(ptr->dirname)) { ptr->dir = opendir(ptr->dirname); if(ptr->dir) { de = readdir(ptr->dir); if(de) { ptr->state = DIR_STATE_OPENED; back = 1; /* back = get_file_properties(ptr, de->d_name); */ if(!get_file_properties(ptr, de->d_name)) { back = -1; } } else { $? "! failed to read entry" closedir(ptr->dir); ptr->dir = NULL; ptr->state = DIR_STATE_CLOSED; } } else { $? "! failed to open dir" } } else { $? "! wrong dir name" } } break; case DIR_STATE_OPENED: { $? ". opened" de = readdir(ptr->dir); if(de) { /* back = get_file_properties(ptr, de->d_name); */ back = 1; if(!get_file_properties(ptr, de->d_name)) { back = -1; } } else { closedir(ptr->dir); ptr->dir = NULL; ptr->state = DIR_STATE_CLOSED; } } break; default: { $? "! wrong state" } break; } } $? "- dkdir_next %d", back return back; } /** Initialize a new directory. @param ptr Directory to initialize. */ static void init_new_directory DK_P1(dk_dir_t *,ptr) { ptr->dir = NULL; } #else /* any unknown directory listing mechanism */ #endif #endif #endif void dkdir_delete DK_P1(dk_dir_t *, ptr) { if(ptr) { char *p; p = ptr->dirname; if(p) { dk_delete(p); } p = ptr->fullname; if(p) { dk_delete(p); } p = ptr->shortname; if(p) { dk_delete(p); } ptr->dirname = ptr->fullname = ptr->shortname = NULL; dk_delete(ptr); } } dk_dir_t * dkdir_new DK_P0() { dk_dir_t *back = NULL; long ml; back = dk_new(dk_dir_t,1); if(back) { char *ptr; back->error_code = DK_ERR_NONE; back->dirname = back->fullname = back->shortname = NULL; ml = back->maxpathlen = dksf_get_maxpathlen(); back->state = DIR_STATE_UNUSED; ptr = dk_new(char,ml); if(ptr) { back->dirname = ptr; } ptr = dk_new(char,ml); if(ptr) { back->fullname = ptr; } ptr = dk_new(char,ml); if(ptr) { back->shortname = ptr; } if(!((back->dirname) && (back->fullname) && (back->shortname))) { dkdir_delete(back); back = NULL; } else { *(back->dirname) = '\0'; *(back->fullname) = '\0'; *(back->shortname) = '\0'; init_new_directory(back); } } return back; } void dkdir_close DK_P1(dk_dir_t *, ptr) { if(ptr) { dkdir_end_search(ptr); dkdir_delete(ptr); } } dk_dir_t * dkdir_open DK_P1(char *, name) { dk_dir_t *back = NULL; if(name) { back = dkdir_new(); if(back) { if(!dkdir_start_search(back,name)) { $? "! Failed to start search for name" dkdir_close(back); back = NULL; } } else { $? "! Failed to allocate memory" } } else { $? "! No directory name" } return back; } char * dkdir_get_fullname(dk_dir_t *ptr) { char *back = NULL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = ptr->fullname; } } return back; } char * dkdir_get_shortname(dk_dir_t *ptr) { char *back = NULL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = ptr->shortname; } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } long dkdir_uid DK_P1(dk_dir_t *, ptr) { long back = 0L; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_uid(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } long dkdir_gid DK_P1(dk_dir_t *, ptr) { long back = 0L; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_gid(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } char * dkdir_ctime DK_P1(dk_dir_t *, ptr) { char *back = NULL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_ctime(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } char * dkdir_atime DK_P1(dk_dir_t *, ptr) { char *back = NULL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_atime(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } char * dkdir_mtime DK_P1(dk_dir_t *, ptr) { char *back = NULL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_mtime(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } int dkdir_filetype DK_P1(dk_dir_t *, ptr) { int back = 0; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_filetype(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } int dkdir_permissions DK_P1(dk_dir_t *, ptr) { int back = 0; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_permissions(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } unsigned long dkdir_inode DK_P1(dk_dir_t *, ptr) { unsigned long back = 0UL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_inode(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } unsigned long dkdir_device DK_P1(dk_dir_t *, ptr) { unsigned long back = 0UL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_device(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } unsigned long dkdir_rdevice DK_P1(dk_dir_t *, ptr) { unsigned long back = 0UL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_rdevice(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } unsigned long dkdir_nlinks DK_P1(dk_dir_t *, ptr) { unsigned long back = 0UL; if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_nlinks(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } dk_long_long_unsigned_t dkdir_size DK_P1(dk_dir_t *, ptr) { #if DK_HAVE_LONG_LONG_INT dk_long_long_unsigned_t back = 0ULL; #else dk_long_long_unsigned_t back = 0UL; #endif if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_size(&(ptr->stbuf)); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } dk_long_long_unsigned_t dkdir_size_ok DK_P2(dk_dir_t *, ptr, int *, ok) { #if DK_HAVE_LONG_LONG_INT dk_long_long_unsigned_t back = 0ULL; #else dk_long_long_unsigned_t back = 0UL; #endif if(ptr) { if(ptr->state == DIR_STATE_OPENED) { back = dkstat_size_ok(&(ptr->stbuf), ok); } else { ptr->error_code = DK_ERR_NOT_NOW; } } return back; } /** File name expander state: Not yet initialized. */ #define FNE_STATE_UNUSED 0 /** File name expander state: Initialized. */ #define FNE_STATE_INITIALIZED 1 /** File name expander state: Opened. */ #define FNE_STATE_OPENED 2 /** File name expander state: Closed. */ #define FNE_STATE_CLOSED 3 /** File name expander state: Search for directories. */ #define FNE_DIRS 8 /** File name expander state: Search for files. */ #define FNE_FILES 16 /** File name expander state: Must run. */ #define FNE_MUST_RUN 32 /** File name expander state: Not yet initialized. */ #define FNE_NOT_STATE (FNE_DIRS | FNE_FILES | FNE_MUST_RUN) /** Correct a directory name. @param name Buffer containing the file name. */ static void correct_dir_name DK_P1(char *, name) { char *ptr; ptr = name; while(*ptr) { #if DK_HAVE_FEATURE_BACKSLASH if(*ptr == '/') { *ptr = '\\'; } #else if(*ptr == '\\') { *ptr = '/'; } #endif ptr++; } } dk_fne_t * dkfne_open DK_P3(char *, name, int, files, int, dirs) { dk_fne_t *back = NULL; $? "+ dkfne_open %s", TR_STR(name) if(name && (files || dirs)) { if(strlen(name) > 0) { back = dkdir_new(); if(back) { if((long)strlen(name) < back->maxpathlen) { strcpy(back->dirname, name); correct_dir_name(back->dirname); back->state = FNE_STATE_INITIALIZED; if(files) { back->state |= FNE_FILES; } if(dirs) { back->state |= FNE_DIRS; } #if USE_FNE if(dkstr_chr(name, '*')) { back->state |= FNE_MUST_RUN; } else { if(dkstr_chr(name, '?')) { back->state |= FNE_MUST_RUN; } } #endif } else { $? "! name too long" dkdir_delete(back); back = NULL; } } else { $? "! failed to allocate mem" } } else { $? "! invalid name" } } else { $? "! invalid arguments" } $? "- dkfne_open %s", TR_PTR(back) return back; } /** Find one file name matching a pattern. @param f File name expander. @return 1 on success, 0 on error. */ static int dkfne_find_one DK_P1(dk_fne_t *, f) { int back = 0; char *ptr; $? "+ dkfne_find_one %s", TR_PTR(f) if(f) { (f->fullname)[0] = '\0'; (f->shortname)[0] = '\0'; if(f->state & FNE_MUST_RUN) { $? ". need to search" #if USE_FNE switch(f->state & (~(FNE_NOT_STATE))) { case FNE_STATE_INITIALIZED: { #if defined(WIN32) || defined(_WIN32) /* + Win32 */ #if DK_HAVE__FINDFIRST64 /* Win32, _findfirst64 */ f->hFile64 = _findfirst64(f->dirname, &(f->fdt64)); if(f->hFile64 != -1L) { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_OPENED); if((long)strlen((f->fdt64).name) < f->maxpathlen) { strcpy(f->shortname, (f->fdt64).name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_NO_SUCH_FILE; } #else #if DK_HAVE__FINDFIRST32 /* Win32, _findfirst32 */ f->hFile32 = _findfirst32(f->dirname, &(f->fdt32)); if(f->hFile32 != -1L) { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_OPENED); if((long)strlen((f->fdt32).name) < f->maxpathlen) { strcpy(f->shortname, (f->fdt).name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_NO_SUCH_FILE; } #else #if DK_HAVE__FINDFIRST /* Win32, _findfirst */ f->hFile = _findfirst(f->dirname, &(f->fdt)); if(f->hFile != -1L) { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_OPENED); if((long)strlen((f->fdt).name) < f->maxpathlen) { strcpy(f->shortname, (f->fdt).name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_NO_SUCH_FILE; } #endif #endif #endif /* - Win32 */ #else #if DK_HAVE_FINDFIRST /* DOS, findfirst */ int i; i = findfirst(f->dirname, &(f->dir), ((f->state & FNE_FILES) ? FA_DIREC : 0)); if(i == 0) { if(strlen((f->dir).ff_name) < f->maxpathlen) { strcpy(f->shortname, (f->dir).ff_name); $? ". short name %s", f->shortname back = 1; f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_OPENED); } else { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_STRING_TOO_LONG; } } else { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_NO_SUCH_FILE; } #else #if DK_HAVE_DIRENT_H /* UNIX/Linux, dirent */ #else /* any unknown directory listing mechanism */ #endif #endif #endif } break; case FNE_STATE_OPENED: { int i; #if defined(WIN32) || defined(_WIN32) /* + Win32 */ #if DK_HAVE__FINDFIRST64 /* Win32, _findfirst64 */ i = _findnext64(f->hFile64, &(f->fdt64)); if(i == 0) { if((long)strlen((f->fdt64).name) < f->maxpathlen) { strcpy(f->shortname, (f->fdt64).name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { _findclose(f->hFile64); f->hFile64 = -1L; f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_FINISHED; } #else #if DK_HAVE__FINDFIRST32 /* Win32, _findfirst32 */ i = _findnext32(f->hFile32, &(f->fdt32)); if(i == 0) { if((long)strlen((f->fdt32).name) < f->maxpathlen) { strcpy(f->shortname, (f->fdt32).name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { _findclose(f->hFile32); f->hFile32 = -1L; f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_FINISHED; } #else #if DK_HAVE__FINDFIRST /* Win32, _findfirst */ i = _findnext(f->hFile, &(f->fdt)); if(i == 0) { if((long)strlen((f->fdt).name) < f->maxpathlen) { strcpy(f->shortname, (f->fdt).name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { _findclose(f->hFile); f->hFile = -1L; f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); f->error_code = DK_ERR_FINISHED; } #endif #endif #endif /* - Win32 */ #else #if DK_HAVE_FINDFIRST /* DOS, findfirst */ i = findnext(&(f->dir)); if(i == 0) { if(strlen((f->dir).ff_name) < f->maxpathlen) { strcpy(f->shortname, (f->dir).ff_name); $? ". short name %s", f->shortname back = 1; } else { f->error_code = DK_ERR_STRING_TOO_LONG; } } else { f->state = ((f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED); } #else #if DK_HAVE_DIRENT_H /* UNIX/Linux, dirent */ #else /* any unknown directory listing mechanism */ #endif #endif #endif } break; default: { $? "! wrong state" f->error_code = DK_ERR_NOT_NOW; } break; } #endif } else { $? ". use name as is" switch(f->state & (~(FNE_NOT_STATE))) { case FNE_STATE_INITIALIZED: { strcpy(f->fullname, f->dirname); ptr = dkstr_rchr(f->fullname, path_component_separator[0]); if(ptr) { ptr++; } else { ptr = f->fullname; } strcpy(f->shortname, ptr); f->state = (FNE_STATE_CLOSED | ((f->state) & FNE_NOT_STATE)); back = 1; } break; default: { $? "! wrong state" f->error_code = DK_ERR_NOT_NOW; } break; } } } if(back) { #if USE_FNE if((f->state) & FNE_MUST_RUN) { $? ". must create full name" strcpy(f->fullname, f->dirname); ptr = dkstr_rchr(f->fullname, path_component_separator[0]); if(ptr) { ptr++; } else { ptr = f->fullname; } strcpy(ptr, f->shortname); $? ". full name created %s", TR_STR((f->fullname)) } #endif } $? "- dkfne_find_one %d", back return back; } int dkfne_next DK_P1(dk_fne_t *, f) { int back = 0; int can_continue, must_continue, ft; char *fullname; dk_stat_t stb; $? "+ dkfne_next %s", TR_PTR(f) if(f) { can_continue = must_continue = 1; while(can_continue && must_continue) { can_continue = dkfne_find_one(f); if(can_continue) { fullname = dkfne_get_fullname(f); if(fullname) { if(dkstat_get(&stb, fullname)) { ft = dkstat_filetype(&stb); ft = ft & (~(DK_FT_SYMLINK)); switch(ft) { case DK_FT_REG : { if((f->state) & FNE_FILES) { back = 1; must_continue = 0; } } break; case DK_FT_DIR : { if((f->state) & FNE_DIRS) { back = 1; must_continue = 0; } } break; } } } } } } $? "- dkfne_next %d", back return back; } char *dkfne_get_one DK_P1(dk_fne_t *, f) { char *back = NULL; char *ptr; if(f) { if(dkfne_next(f)) { ptr = dkfne_get_fullname(f); if(ptr) { back = dkstr_dup(ptr); if(back) { if(dkfne_next(f)) { dk_delete(back); back = NULL; f->error_code = DK_ERR_NOT_UNIQUE; } } else { f->error_code = DK_ERR_NOMEM; } } else { f->error_code = DK_ERR_NO_SUCH_FILE; } } else { f->error_code = DK_ERR_NO_SUCH_FILE; } } return back; } char * dkfne_get_fullname DK_P1(dk_fne_t *, f) { char *back = NULL; $? "+ *dkfne_get_fullname %s", TR_PTR(f) if(f) { back = f->fullname; } $? "- *dkfne_get_fullname %s", TR_STR(back) return back; } char * dkfne_get_shortname DK_P1(dk_fne_t *, f) { char *back = NULL; $? "+ dkfne_get_shortname %s", TR_PTR(f) if(f) { back = f->shortname; } $? "- dkfne_get_shortname %s", TR_STR(back) return back; } void dkfne_close DK_P1(dk_fne_t *, f) { $? "- dkfne_close %s", TR_PTR(f) if(f) { #if USE_FNE switch(f->state & (~(FNE_NOT_STATE))) { case FNE_STATE_OPENED: { #if defined(WIN32) || defined(_WIN32) /* + Win32 */ #if DK_HAVE__FINDFIRST64 /* Win32, _findfirst64 */ _findclose(f->hFile64); f->hFile64 = -1L; f->state = (f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED; #else #if DK_HAVE__FINDFIRST32 /* Win32, _findfirst32 */ _findclose(f->hFile32); f->hFile32 = -1L; f->state = (f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED; #else #if DK_HAVE__FINDFIRST /* Win32, _findfirst */ _findclose(f->hFile); f->hFile = -1L; f->state = (f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED; #endif #endif #endif /* - Win32 */ #else #if DK_HAVE_FINDFIRST /* DOS, findfirst */ int i; i = 0; while(!i) { i = findnext(&(f->dir)); } f->state = (f->state & FNE_NOT_STATE) | FNE_STATE_CLOSED; #else #if DK_HAVE_DIRENT_H /* UNIX/Linux, dirent */ #else /* any unknown directory listing mechanism */ #endif #endif #endif } break; default: { $? "! wrong state" } break; } #endif } $? "- dkfne_close" } char * dksf_get_last_filename DK_P1(char *, name) { char *back = NULL; if(name) { back = dkstr_rchr(name, path_component_separator[0]); if(back) { back++; } else { back = name; } } return back; } char * dksf_get_file_type_dot DK_P1(char *, name) { char *back = NULL; char *x; $? "+ dksf_get_file_type_dot %s", TR_STR(name) if(name) { x = dkstr_rchr(name, path_component_separator[0]); x = (x ? x : name); back = dkstr_rchr(x, '.'); } $? "- dksf_get_file_type_dot %s", TR_STR(back) return back; } int dksf_is_abs_path DK_P1(char *, name) { int back = 0; $? "+ dksf_is_abs_path %s", TR_STR(name) if(name) { if(*name == path_component_separator[0]) { back = 1; } else { #if DK_HAVE_FEATURE_DRIVECHAR if(((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) { if(name[1] == ':') { if(name[2] == path_component_separator[0]) { if(name[3]) { back = 1; } } } } #endif } } $? "- dksf_is_abs_path %d", back return back; } /** Find place where tu cut a file name. @param dirname Directory name. @return Pointer to cut position. */ static char * find_place_to_cut DK_P1(char *, dirname) { char *back = NULL; char *ptr; int seps_found; int last_was_sep; $? "+ find_place_to_cut %s", TR_STR(dirname) last_was_sep = 0; seps_found = 0; ptr = dirname; while(*ptr) { if(*ptr == path_component_separator[0]) { seps_found++; last_was_sep = 1; if(seps_found > 1) { back = ptr; } } else { if(last_was_sep) { if(seps_found == 1) { back = ptr; } } last_was_sep = 0; } ptr++; } $? "- find_place_to_cut %s", TR_STR(back) return back; } int dksf_path_combine DK_P4(char *, buf, size_t, len, char *, cd, char *, pr) { int back = 0; size_t used; char *xptr, *yptr, *zptr; if(buf) { if(len > 3) { if(cd) { if(pr) { used = strlen(cd); if(used < len) { back = 1; strcpy(buf, cd); xptr = pr; if(dksf_is_abs_path(pr)) { xptr++; *buf = pr[0]; if(*buf != path_component_separator[0]) { buf[1] = pr[1]; buf[2] = pr[2]; buf[3] = '\0'; xptr++; xptr++; } else { buf[1] = '\0'; } used = strlen(buf); } while(xptr && back) { used = strlen(buf); yptr = dkstr_chr(xptr, path_component_separator[0]); if(yptr) { *yptr = '\0'; } if(strcmp(xptr, ".")) { if(strcmp(xptr, "..")) { $? ". add component" if((used + strlen(xptr) + 1) < len) { if(buf[(used > 0) ? (used - 1) : used] != path_component_separator[0]) { strcat(buf, path_component_separator); } strcat(buf, xptr); } else { back = 0; } } else { $? ". one dir upward" /* zptr = dkstr_rchr(buf, path_component_separator[0]); */ zptr = find_place_to_cut(buf); if(zptr) { *zptr = '\0'; } else { back = 0; } } } if(yptr) { *yptr = path_component_separator[0]; } xptr = yptr; if(xptr) xptr++; } } } } } } return back; } #if DK_HAVE_FEATURE_DOS_EXEC /** Check whether a file name exists with one of the specified suffixes. @param buf Buffer containing the base file name. @param len Length of \a buf. @param pe List of suffixes for executable files, semicolon separated. @return 1 on success, 0 on error. */ static int check_executable_file(char *buf, size_t len, char *pe) { int back = 0; size_t lgt; dk_stat_t st; char *xptr, *yptr; if(dksf_get_file_type_dot(buf)) { $? ". extension specified" if(dkstat_get(&st, buf)) { if((dkstat_filetype(&st) & (~(DK_FT_SYMLINK))) == DK_FT_REG) { back = 1; } } } else { $? ". try all extensions" lgt = strlen(buf); xptr = pe; while(xptr && (!back)) { yptr = dkstr_chr(xptr, ';'); if(yptr) { *(yptr++) = '\0'; } if((lgt + strlen(xptr)) < len) { strcat(buf, xptr); if(dkstat_get(&st, buf)) { if((dkstat_filetype(&st) & (~(DK_FT_SYMLINK))) == DK_FT_REG) { back = 1; } } } if(!back) { buf[lgt] = '\0'; } xptr = yptr; } } return back; } #endif int dksf_get_executable DK_P5(char *, buf, size_t, len, char *, cd, char *, pr, int, cu) { int back = 0; char psep; int action; char *pathori; char *pathcp; #if DK_HAVE_FEATURE_DOS_EXEC char *pe; char *pc; #endif char *xptr; char *yptr; size_t used; $? "+ dksf_get_executable %s %lu %s %s", TR_PTR(buf), (unsigned long)len, TR_STR(cd), TR_STR(pr) if(buf) { if(len) { if(cd) { if(pr) { $? ". arguments ok" psep = path_component_separator[0]; if(dkstr_chr(pr,psep)) { action = 2; } else { action = 0; } if(dksf_get_file_type_dot(pr)) { action += 1; } #if DK_HAVE_FEATURE_DOS_EXEC #if DK_HAVE_GETMODULEFILENAME && DK_HAVE_GETMODULEHANDLE if(cu) { if(GetModuleFileNameA(GetModuleHandle(NULL),buf,len)) { back = 1; } } #endif /* DOS exec search, current directory first */ if(!back) { pe = getenv("PATHEXT"); if(!pe) pe = default_path_ext; pc = dkstr_dup(pe); if(pc) { if(action & 2) { $? ". inspect path as specified in pr" if(len > strlen(pr)) { strcpy(buf, pr); back = check_executable_file(buf, len, pc); } } else { $? ". path from PATH, current dir first" if(len > (strlen(cd) + strlen(pr) + 1)) { strcpy(buf, cd); used = strlen(cd); if(used > 0) used--; if(buf[used] != path_component_separator[0]) { strcat(buf, path_component_separator); } strcat(buf, pr); back = check_executable_file(buf, len, pc); } if(!back) { pathori = getenv("PATH"); if(pathori) { pathcp = dkstr_dup(pathori); if(pathcp) { xptr = pathcp; while(xptr && (!back)) { strcpy(pc, pe); yptr = dkstr_chr(xptr, ';'); if(yptr) { *(yptr++) = '\0'; } if(len > (strlen(xptr) + 1 + strlen(pr))) { strcpy(buf, xptr); used = strlen(buf); if(used > 0) used--; if(buf[used] != path_component_separator[0]) { strcat(buf, path_component_separator); } strcat(buf, pr); back = check_executable_file(buf, len, pc); } xptr = yptr; } dkmem_free(pathcp); } } } } dkmem_free(pc); } } #else /* UNIX exec search, consult PATH/path */ if(action & 2) { $? ". inspect path as specified in pr" if(dksf_is_abs_path(pr)) { if(strlen(pr) < len) { strcpy(buf,pr); back = 1; } } else { back = dksf_path_combine(buf, len, cd, pr); } } else { $? ". do search" pathori = getenv("PATH"); if(pathori) { dk_stat_t st; pathcp = dkstr_dup(pathori); if(pathcp) { xptr = pathcp; while(xptr && (!back)) { $? ". remaining path %s", xptr yptr = dkstr_chr(xptr, ':'); if(yptr) { *(yptr++) = '\0'; } $? ". checking directory %s", xptr if(strlen(xptr) == 0) { $? ". current dir" if(len > (strlen(cd) + strlen(pr) + 1)) { $? ". length ok" strcpy(buf, cd); used = strlen(cd); if(used > 0) used--; if(buf[used] != path_component_separator[0]) { strcat(buf, path_component_separator); } strcat(buf, pr); if(dkstat_get(&st, buf)) { if((dkstat_filetype(&st) & (~DK_FT_SYMLINK)) == DK_FT_REG) { if(dkstat_permissions(&st) & DK_PERM_U_EXECUTE) { back = 1; } } } } } else { $? ". specified dir" if(len > (strlen(xptr) + strlen(pr) + 1)) { strcpy(buf, xptr); used = strlen(xptr); if(used > 0) used--; if(buf[used] != path_component_separator[0]) { strcat(buf, path_component_separator); } strcat(buf, pr); if(dkstat_get(&st, buf)) { if((dkstat_filetype(&st) & (~DK_FT_SYMLINK)) == DK_FT_REG) { if(dkstat_permissions(&st) & DK_PERM_U_EXECUTE) { back = 1; } } } } } xptr = yptr; } dkmem_free(pathcp); } } } #endif } } } } $? "- dksf_get_executable %d", back return back; } int dksf_getcwd DK_P2(char *, buffer, size_t, lgt) { int back = 0; if(buffer && lgt) { #if DK_HAVE_GETCURRENTDIRECTORY if(GetCurrentDirectoryA(lgt,buffer)) { back = 1; } #else #if DK_HAVE_GETCWD if(getcwd(buffer, lgt)) { back = 1; } #else #if DK_HAVE_GETWD char *buf; buf = dk_new(char,DK_MAX_PATH); if(buf) { if(getwd(buf)) { if(strlen(buf) < lgt) { strcpy(buffer, buf); back = 1; } } dk_delete(buf); buf = NULL; } #else #if DK_HAVE__GETCWD if(_getcwd(buffer, lgt)) { back = 1; } #else #if DK_HAVE__GETWD char *buf; buf = dk_new(char,DK_MAX_PATH); if(buf) { if(_getwd(buf)) { if(strlen(buf) < lgt) { strcpy(buffer, buf); back = 1; } } dk_delete(buf); buf = NULL; } #else #error "No getcwd/getwd/_getcwd/_getwd function" #endif #endif #endif #endif #endif } return back; } void dksf_correct_fnsep DK_P1(char *,str) { char *ptr; if(str) { ptr = str; while(*ptr) { if(*ptr == no_component_separator[0]) { *ptr = path_component_separator[0]; } ptr++; } } } int dksf_remove_file DK_P1(char *, filename) { int back = 0; $? "+ dksf_remove_file %s", TR_STR(filename) if(filename) { #if DK_HAVE_UNLINK || DK_HAVE__UNLINK $? ". try unlink" #if DK_HAVE_UNLINK if(unlink(filename) == 0) { #else if(_unlink(filename) == 0) { #endif back = 1; } #else #if DK_HAVE_REMOVE $? ". try remove" if(remove(filename) == 0) { back = 1; } #endif #endif } $? "- dksf_remove_file %d", back return back; } /** Attempt to remove a directory with all contents. @param filename File name of directory. @param bck Set to 0 on error. */ static void remove_dir_rec DK_P2(char *, filename, int *, bck) { dk_stat_t st; dk_dir_t *dir; char *sn, *fn; int dnt; $? "+ remove_dir_rec %s %s", TR_STR(filename), TR_PTR(bck) if(dkstat_get(&st, filename)) { if((st.filetype) & DK_FT_SYMLINK) { $? ". symlink" if(!dksf_remove_file(filename)) { $? "! failed to remove symlink %s", TR_STR(filename) *bck = 0; } } else { $? ". not a symlink" switch(st.filetype) { case DK_FT_DIR : { $? ". directory" dir = dkdir_open(filename); if(dir) { while((dnt = dkdir_next(dir))) { if(dnt == 1) { sn = dir->shortname; fn = dir->fullname; if(sn && fn) { if(strcmp(sn, ".")) { if(strcmp(sn, "..")) { remove_dir_rec(fn, bck); } } } else { $? "! failed to obtain full or shortname" *bck = 0; } } } dkdir_close(dir); dir = NULL; #if DK_HAVE_RMDIR || DK_HAVE__RMDIR $? ". trying rmdir" #if DK_HAVE_RMDIR if(rmdir(filename) != 0) #else if(_rmdir(filename) != 0) #endif { $? "! failed to rmdir dir %s", TR_STR(filename) *bck = 0; } #else #if DK_HAVE_UNLINK || DK_HAVE__UNLINK $? ". trying unlink" #if DK_HAVE_UNLINK if(unlink(filename) != 0) #else if(_unlink(filename) != 0) #endif { $? "! failed to unlink dir %s", TR_STR(filename) *bck = 0; } #else #if DK_HAVE_REMOVE $? ". trying remove" if(remove(filename) != 0) { $? "! failed to remove dir %s", TR_STR(filename) *bck = 0; } #else $? "! dont know how to delete directories" #endif #endif #endif } else { $? "! failed to open directory %s", TR_STR(filename) *bck = 0; } } break; default : { $? ". not a directory" if(!dksf_remove_file(filename)) { $? "! failed to dksf_remove_file %s", TR_STR(filename) *bck = 0; } } break; } } } else { $? "! invalid file name" *bck = 0; } $? "- remove_dir_rec" } int dksf_remove_directory DK_P1(char *, filename) { int back = 0; if(filename) { back = 1; remove_dir_rec(filename, &back); } return back; } dk_stat_t * dkdir_stat DK_P1(dk_dir_t *,d) { dk_stat_t *back = NULL; if(d) { back = &(d->stbuf); } return back; } int dksf_fdesk_binary DK_P2(int,fn, int,fl) { int back = 0; #if DK_HAVE_DOSWIN_SETMODE int res = 0; #endif #if DK_HAVE_DOSWIN_SETMODE if(fl) { #if DK_HAVE_DOSWIN_SETMODE #if DK_HAVE_SETMODE #ifdef O_BINARY res = setmode(fn, O_BINARY); if(res == O_BINARY) back = 1; #else #ifdef _O_BINARY res = setmode(fn, _O_BINARY); if(res == _O_BINARY) back = 1; #endif #endif #else #if DK_HAVE__SETMODE #ifdef O_BINARY res = _setmode(fn, O_BINARY); if(res == O_BINARY) back = 1; #else #ifdef _O_BINARY res = _setmode(fn, _O_BINARY); if(res == _O_BINARY) back = 1; #endif #endif #endif #endif #endif } else { #if DK_HAVE_DOSWIN_SETMODE #if DK_HAVE_SETMODE #ifdef O_TEXT res = setmode(fn, O_TEXT); if(res == O_BINARY) back = 1; #else #ifdef _O_TEXT res = setmode(fn, _O_TEXT); if(res == _O_BINARY) back = 1; #endif #endif #else #if DK_HAVE__SETMODE #ifdef O_TEXT res = _setmode(fn, O_TEXT); if(res == O_BINARY) back = 1; #else #ifdef _O_TEXT res = _setmode(fn, _O_TEXT); if(res == _O_BINARY) back = 1; #endif #endif #endif #endif #endif } #endif return back; } /** Check whether a file name is a symbolic link. @param name File name. @return 1 for symbolic link, 0 for other file types. */ static int is_symbolic_link DK_P1(char *,name) { int back = 0; dk_stat_t st; if(name) { dkstat_init(&st); if(dkstat_get(&st, name)) { if((st.filetype) & DK_FT_SYMLINK) { back = 1; } } } $? "= is_symbolic_link %s -> %d", TR_STR(name), back return back; } /** Check whether a file name is a directory. @param name File name to check. @return 1 for directory, 0 for not a directory. */ static int is_directory DK_P1(char *,name) { int back = 0; dk_stat_t st; if(name) { dkstat_init(&st); if(dkstat_get(&st, name)) { if(((st.filetype) & (~(DK_FT_SYMLINK))) == DK_FT_DIR) { back = 1; } } } $? "= is_directory %s -> %d", TR_STR(name), back return back; } /** When opening a file to write check that it is not a directory. @param name File name to open. @param ign Security checks to ignore. @param reason Pointer to buffer for reason. @return 1 on success (we can write the file), 0 on error. */ static int directory_write_check DK_P3(char *,name,int,ign,int *,reason) { int back = 1; dk_stat_t st; if(name) { if(dkstat_get(&st, name)) { if((st.permissions) & DK_PERM_O_WRITE) { if(!(ign & DK_SF_SEC_WO)) { back = 0; if(reason) *reason = DK_SF_SEC_WO; } } if((st.permissions) & DK_PERM_G_WRITE) { if(!(ign & DK_SF_SEC_WG)) { back = 0; if(reason) *reason = DK_SF_SEC_WG; } } } } $? "- directory_write_check %d", back return back; } /** Check whether the link target is owned by the same user as the link itself. @param name File name. @return 1 for check ok, 0 for check failed. */ static int check_ownership_for_symlink DK_P1(char *,name) { int back = 0; dk_stat_t st; if(name) { if(dkstat_get(&st, name)) { if(st.ud) { back = 1; } } } $? "- check_ownership_for_symlink %d", back return back; } int dksf_allowed_to_write DK_P3(char *,name,int,ign,int *,reason) { int back = 0; char *dirname; char *cptr; size_t lgt; $? "+ dksf_allowed_to_write %s %d", TR_STR(name), ign if(name) { if(is_symbolic_link(name)) { dirname = dkstr_dup(name); if(dirname) { cptr = dkstr_rchr(dirname, path_component_separator[0]); if(cptr) { *cptr = (char)0; if((lgt = strlen(dirname)) > 0) { #if DK_HAVE_DOS_DRIVE_LETTER if(lgt == 2) { if(dirname[1] == str_colon) { dirname[2] = path_component_separator[0]; dirname[3] = (char)0; } } #endif /* DK_HAVE_DOS_DRIVE_LETTER */ back = directory_write_check(dirname,ign,reason); } else { dirname[0] = path_component_separator[0]; dirname[1] = (char)0; back = directory_write_check(dirname,ign,reason); } } else { back = directory_write_check(curdir,ign,reason); } dk_delete(dirname); } if(back) { if(!(ign & DK_SF_SEC_OWNER)) { if(!check_ownership_for_symlink(name)) { back = 0; if(reason) { *reason = DK_SF_SEC_OWNER; } } } } } else { back = 1; } } $? "- dksf_allowed_to_write %d", back return back; } FILE * dksf_msfo DK_P4(char *,name,char *,mode,int,ign,int *,reason) { FILE *back = NULL; int want_to_write; char *cptr; $? "+ dksf_msfo %s %s %d %s", TR_STR(name), TR_STR(mode), ign, TR_PTR(reason) if(name && mode) { want_to_write = 0; cptr = mode; while(*cptr) { switch(*(cptr++)) { case 'w': case 'a': case '+': { want_to_write = 1; } break; } } if(want_to_write) { $? ". want to write" if(dksf_allowed_to_write(name,ign,reason)) { if(is_directory(name)) { if(reason) { *reason = DK_SF_SEC_DIR; } } else { $? ". allowed to write" #if DK_HAVE_LARGEFILE64_SOURCE && DK_HAVE_FOPEN64 back = fopen64(name,mode); #else back = fopen(name,mode); #endif } } } else { $? ". do not want to write" if(is_directory(name)) { if(reason) { *reason = DK_SF_SEC_DIR; } } else { #if DK_HAVE_LARGEFILE64_SOURCE && DK_HAVE_FOPEN64 back = fopen64(name, mode); #else back = fopen(name,mode); #endif } } } $? "- dksf_msfo %s", TR_PTR(back) return back; } FILE * dksf_fopen DK_P2(char *,p,char *,m) { FILE *back = NULL; int dummy = 0; back = dksf_msfo(p,m,0,&dummy); return back; } int dksf_must_expand_filename DK_P1(char *,name) { int back = 0; #if DK_HAVE_FEATURE_BACKSLASH && USE_FNE char *ptr; ptr = name; while((!back) && (*ptr)) { if((*ptr == '?') || (*ptr == '*')) { back = 1; } ptr++; } #endif return back; } int dkfne_get_error_code DK_P2(dk_fne_t *,f, int, res) { int back = DK_ERR_NONE; if(f) { back = f->error_code; if(res) { f->error_code = DK_ERR_NONE; } } return back; } int dksf_get_filetype DK_P1(char *,pathname) { int back = 0; dk_stat_t st; $? "+ dksf_get_filetype %s", TR_STR(pathname) if(pathname) { dkstat_init(&st); if(dkstat_get(&st, pathname)) { back = st.filetype; } } $? "- dksf_get_filetype %d", back return back; } int dksf_is_directory DK_P1(char *,pathname) { int back = 0; int ft = 0; $? "+ dksf_is_directory %s", TR_STR(pathname) if(pathname) { ft = dksf_get_filetype(pathname); ft &= (~DK_FT_SYMLINK); if(ft == DK_FT_DIR) { back = 1; } } $? "- dksf_is_directory %d", back return back; } int dksf_no_core DK_P0() { int back = 0; #if DK_HAVE_SYS_RESOURCE_H #if DK_HAVE_GETRLIMIT #ifdef RLIMIT_CORE struct rlimit rl; rl.rlim_cur = rl.rlim_max = 0; if(setrlimit(RLIMIT_CORE, &rl) == 0) { back = 1; } #endif #endif #endif return back; } /* Usage: dk_echo_t echodata; if(dksf_echo_save(&echodata)) { dksf_echo_off(&echodata); ... dksf_echo_restore(&echodata); } */ int dksf_echo_save DK_P1(dk_echo_t *,ep) { int back = 0; $? "+ dksf_echo_save" if(ep) { ep->is_tty = 0; #if DK_HAVE_TCGETATTR $? ". /1/" if(tcgetattr(0, &(ep->ori)) == 0) { back = 1; } #if DK_HAVE_ISATTY $? ". /1a/" ep->is_tty = isatty(0); #endif #else #ifdef TCGETS $? ". /2/" if(ioctl(0, TCGETS, &(ep->ori)) == 0) { back = 1; } #if DK_HAVE_ISATTY $? ". /2a/" ep->is_tty = isatty(0); #endif #else #if DK_HAVE_GETSTDHANDLE $? ". /3/" ep->consoleHandle = GetStdHandle(STD_INPUT_HANDLE); if(ep->consoleHandle != INVALID_HANDLE_VALUE) { ep->is_tty = 1; if(GetConsoleMode(ep->consoleHandle, &(ep->ori))) { back = 1; } } #else #if DK_HAVE_ISATTY $? ". /4/" ep->is_tty = isatty(0); #endif #endif #endif #endif } $? "- dksf_echo_save %d", back return back; } int dksf_echo_restore DK_P1(dk_echo_t *,ep) { int back = 0; $? "+ dksf_echo_restore" if(ep) { #if DK_HAVE_TCGETATTR $? ". /1/" if(tcsetattr(0, TCSANOW, &(ep->ori)) == 0) { back = 1; } #else #ifdef TCGETS $? ". /2/" if(ioctl(0, TCSETS, &(ep->ori)) == 0) { back = 1; } #else #if DK_HAVE_GETSTDHANDLE $? ". /3/" if(ep->consoleHandle != INVALID_HANDLE_VALUE) { if(SetConsoleMode(ep->consoleHandle, ep->ori)) { back = 1; } } #endif #endif #endif } $? "- dksf_echo_restore %d", back return back; } /** Abbreviation for use with sizeof operator. */ typedef struct termios TIO; int dksf_echo_off DK_P1(dk_echo_t *,ep) { int back = 0; $? "+ dksf_echo_off" if(ep) { #if DK_HAVE_TCGETATTR struct termios nti; $? ". /1/" DK_MEMCPY(&nti, &(ep->ori), sizeof(TIO)); #ifdef ECHO $? ". ECHO" nti.c_lflag &= (~(ECHO)); #endif #ifdef ECHONL $? ". ECHONL" nti.c_lflag |= (ECHONL); #endif if(tcsetattr(0, TCSANOW, &nti) == 0) { back = 1; } tcflush(0, TCIFLUSH); #else #ifdef TCGETS struct termios nti; $? ". /2/" DK_MEMCPY(&nti, &(ep->ori), sizeof(TIO)); #ifdef ECHO $? ". ECHO" nti.c_lflag &= (~(ECHO)); #endif #ifdef ECHONL $? ". ECHONL" nti.c_lflag |= (ECHONL); #endif if(ioctl(0, TCSETS, &nti) == 0) { back = 1; } (void)ioctl(0, TCFLSH, 0); #else #if DK_HAVE_GETSTDHANDLE DWORD nti; $? ". /3/" nti = ep->ori; if(ep->consoleHandle != INVALID_HANDLE_VALUE) { nti &= (~(ENABLE_ECHO_INPUT)); if(SetConsoleMode(ep->consoleHandle, nti)) { back = 1; } } #endif #endif #endif } $? "- dksf_echo_off %d", back return back; } int dksf_echo_is_tty DK_P1(dk_echo_t *,ep) { int back = 0; if(ep) { back = ep->is_tty; } $? "= dksf_echo_is_tty %d", back return back; } int dksf_echo_test_tty DK_P0() { int back = 0; $? "+ dksf_echo_test_tty" #if DK_HAVE_TCGETATTR #if DK_HAVE_ISATTY $? ". /1/" back = isatty(0); #endif #else #ifdef TCGETS #if DK_HAVE_ISATTY $? ". /2/" back = isatty(0); #endif #else #if DK_HAVE_GETSTDHANDLE $? ". /3/" if(GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE) { back = 1; } #else #if DK_HAVE_ISATTY $? ". /4/" back = isatty(0); #endif #endif #endif #endif $? "- dksf_echo_test_tty %d", back return back; } unsigned long dksf_filesize_bytes DK_P0() { unsigned long back = 0UL; #if defined(WIN32) || defined(_WIN32) #if DK_HAVE__STAT64 back = 8UL; #else #if DK_HAVE__STAT32 back = 4UL; #else back = (unsigned long)sizeof(off_t); #endif #endif #else #if DK_HAVE_STAT64 && DK_HAVE_LARGEFILE64_SOURCE back = 8UL; #else back = (unsigned long)sizeof(off_t); #endif #endif return back; } unsigned long dksf_long_long_bytes DK_P0() { return (unsigned long)sizeof(dk_long_long_unsigned_t); } /** Write PID file. @param appname Application name. @param cr 1=create, 0=delete @return 1 on success, 0 on error. */ int dksf_write_pid_file DK_P2(char *,appname, int,cr) { int back = 0; size_t sz = 0; FILE *fipo = NULL; char buffer[MY_MAXPATHLEN]; if(appname) { sz = strlen(var_run); sz += strlen(path_component_separator); sz += strlen(appname); sz += strlen(suffix_pid); if(sz < sizeof(buffer)) { strcpy(buffer, var_run); strcat(buffer, path_component_separator); strcat(buffer, appname); strcat(buffer, suffix_pid); switch(cr) { case 1: { fipo = dksf_fopen(buffer, "w"); if(fipo) { fprintf(fipo, "%ld\n", dksf_getpid()); fclose(fipo); fipo = NULL; } } break; default: { back = dksf_remove_file(buffer); } break; } } } return back; }