Annotation of parser3/src/main/pa_dir.C, revision 1.35

1.1       paf         1: /** @file
                      2:        Parser: directory scanning for different OS-es.
                      3: 
1.34      moko        4:        Copyright (c) 2000-2026 Art. Lebedev Studio (https://www.artlebedev.com)
1.32      moko        5:        Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
1.12      paf         6: */
1.1       paf         7: 
1.9       paf         8: #include "pa_common.h"
1.1       paf         9: #include "pa_dir.h"
1.28      moko       10: #include "pa_request.h"
                     11: #include "pa_convert_utf.h"
1.1       paf        12: 
1.35    ! moko       13: volatile const char * IDENT_PA_DIR_C="$Id: pa_dir.C,v 1.34 2026/04/25 13:38:46 moko Exp $" IDENT_PA_DIR_H;
        !            14: 
        !            15: #ifdef WIN32
        !            16: bool is_os_absolute_path(const String& path) {
        !            17:        return is_os_absolute_path(path.cstr());
        !            18: }
        !            19: 
        !            20: bool is_os_absolute_path(const char* path) {
        !            21:        return path[0] && path[0]!=':' && path[1]==':' // DRIVE: (including drive-relative paths, for compatibility)
        !            22:                || path[0]=='\\' && path[1]=='\\' // UNC
        !            23:                || path[0]=='/' && path[1]=='/';
        !            24: }
        !            25: #endif
1.21      moko       26: 
1.24      moko       27: #ifdef _MSC_VER
1.1       paf        28: 
1.28      moko       29: const UTF16* pa_utf16_encode(const char* in, Charset& source_charset);
                     30: const char* pa_utf16_decode(const UTF16* in, Charset& asked_charset);
                     31: 
1.22      moko       32: #define TICKS_PER_SECOND 10000000ULL
                     33: #define EPOCH_DIFFERENCE 11644473600ULL
1.28      moko       34: 
1.22      moko       35: time_t filetime_to_timet(FILETIME const& ft){
                     36:        ULARGE_INTEGER ull;
                     37:        ull.LowPart = ft.dwLowDateTime;
                     38:        ull.HighPart = ft.dwHighDateTime;
                     39:        long long secs=(ull.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE);
                     40:        time_t t =(time_t)secs;
                     41:        return (secs == (long long)t) ? t : 0;
                     42: }
                     43: 
1.16      paf        44: bool findfirst(const char* _pathname, struct ffblk *_ffblk, int /*_attrib*/) {
1.1       paf        45:        char mask[MAXPATH];
                     46:        snprintf(mask, MAXPATH, "%s/*.*", _pathname);
                     47: 
1.28      moko       48:        const UTF16* utf16mask=pa_utf16_encode(mask, pa_thread_request().charsets.source());
                     49: 
                     50:        _ffblk->handle=FindFirstFileW((const wchar_t *)utf16mask, &_ffblk->stat);
1.1       paf        51:        return _ffblk->handle==INVALID_HANDLE_VALUE;
                     52: }
                     53: 
                     54: bool findnext(struct ffblk *_ffblk) {
1.28      moko       55:        return !FindNextFileW(_ffblk->handle, &_ffblk->stat);
1.22      moko       56: }
1.1       paf        57: 
                     58: void findclose(struct ffblk *_ffblk) {
                     59:        FindClose(_ffblk->handle);
                     60: }
                     61: 
1.28      moko       62: const char *ffblk::name() {
                     63:        return pa_utf16_decode((const UTF16*)stat.cFileName, pa_thread_request().charsets.source());
                     64: }
                     65: 
1.25      moko       66: bool ffblk::is_dir(bool) {
1.28      moko       67:        return (stat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
1.22      moko       68: }
                     69: 
                     70: double ffblk::size() {
                     71:        ULARGE_INTEGER ull;
1.28      moko       72:        ull.LowPart = stat.nFileSizeLow;
                     73:        ull.HighPart = stat.nFileSizeHigh;
1.22      moko       74:        return (double)ull.QuadPart;
                     75: }
                     76: 
                     77: time_t ffblk::c_timestamp() {
1.28      moko       78:        return filetime_to_timet(stat.ftCreationTime);
1.22      moko       79: }
                     80: 
                     81: time_t ffblk::m_timestamp() {
1.28      moko       82:        return filetime_to_timet(stat.ftLastWriteTime);
1.22      moko       83: }
                     84: 
                     85: time_t ffblk::a_timestamp() {
1.28      moko       86:        return filetime_to_timet(stat.ftLastAccessTime);
1.22      moko       87: }
                     88: 
1.1       paf        89: #else
                     90: 
1.18      paf        91: bool findfirst(const char* _pathname, struct ffblk *_ffblk, int /*_attrib*/) {
1.23      moko       92:        _ffblk->filePath=_pathname;
1.1       paf        93:        if(!(_ffblk->dir=opendir(_ffblk->filePath)))
1.28      moko       94:                return true;
1.1       paf        95: 
                     96:        return findnext(_ffblk);
                     97: }
                     98: 
                     99: bool findnext(struct ffblk *_ffblk) {
1.28      moko      100:        while(true) {
                    101:                struct dirent *entry=readdir(_ffblk->dir);
                    102:                if(!entry)
                    103:                        return true;
1.1       paf       104: 
1.31      moko      105:                pa_strncpy(_ffblk->ff_name, entry->d_name, sizeof(_ffblk->ff_name));
                    106: 
1.22      moko      107: #ifdef HAVE_STRUCT_DIRENT_D_TYPE
                    108:                // http://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html
                    109:                _ffblk->_d_type=entry->d_type;
                    110: #endif
1.1       paf       111:                return false;
                    112:     }
                    113: }
                    114: 
                    115: void findclose(struct ffblk *_ffblk) {
                    116:        closedir(_ffblk->dir);
                    117: }
                    118: 
1.22      moko      119: void ffblk::stat_file() {
                    120:        char fileSpec[MAXPATH];
                    121:        snprintf(fileSpec, MAXPATH, "%s/%s", filePath, ff_name);
                    122:        
1.27      moko      123:        if(pa_stat(fileSpec, &_st) != 0) {
1.22      moko      124:                memset(&_st,0,sizeof(_st));
                    125:        }
                    126: }
                    127: 
1.25      moko      128: bool ffblk::is_dir(bool stat) {
1.22      moko      129: #ifdef HAVE_STRUCT_DIRENT_D_TYPE
1.25      moko      130:        if(!stat && _d_type != DT_UNKNOWN)
                    131:                return _d_type == DT_DIR;
                    132: #endif
                    133:        stat_file();
1.22      moko      134:        return S_ISDIR(_st.st_mode) != 0;
                    135: }
                    136: 
                    137: double ffblk::size() {
                    138:        return (double)_st.st_size;
                    139: }
                    140: 
                    141: time_t ffblk::c_timestamp() {
                    142:        return _st.st_ctime;
                    143: }
                    144: 
                    145: time_t ffblk::m_timestamp() {
                    146:        return _st.st_mtime;
                    147: }
                    148: 
                    149: time_t ffblk::a_timestamp() {
                    150:        return _st.st_atime;
                    151: }
                    152: 
1.1       paf       153: #endif

E-mail: