source: cpp/common/virtfile/stdiofile.cpp @ 1333

Last change on this file since 1333 was 1332, checked in by Maciej Komosinski, 7 days ago

Compatibility of file stat() and utime() with Embarcadero C++Builder compiler

  • Property svn:eol-style set to native
File size: 4.8 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[1328]2// Copyright (C) 1999-2024  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[109]4
5#include "stdiofile.h"
6#include <common/nonstd_dir.h>
7#include <common/nonstd_stdio.h>
[375]8#include <common/log.h>
[281]9#include <common/Convert.h>
[425]10#ifdef __ANDROID__
11#include <common/dirs.h>
12#include <common/platform/android/AndroidAPK_DIR.h>
13#endif
[1328]14#include <sys/stat.h>
15#include <unistd.h>
16#ifdef _WIN32
17#include <sys/utime.h>
18#else
19#include <utime.h>
20#endif
[109]21
[281]22VirtFILE* StdioFileSystem::Vfopen(const char *path, const char *mode)
[109]23{
[375]24        //log_printf("Vfopen %s %s",path,mode);
[374]25#if defined USE_MFILE || defined _WIN32
[281]26        MFILE *f = mfopen(path, mode);
[206]27#else
[281]28        FILE *f = fopen(path, mode);
[206]29#endif
[375]30        //log_printf("%p",f);
[298]31        if (f) return new StdioFILE(f, path); else return NULL;
[109]32}
33
34VirtDIR* StdioFileSystem::Vopendir(const char* path)
35{
[375]36        //log_printf("Vopendir %s",path);
[425]37#ifdef __ANDROID__
[820]38        int resources_prefix_length = getAppResourcesDir().length();
[425]39        if (strncmp(path, getAppResourcesDir().c_str(), resources_prefix_length) == 0) //it is a resources dir
40        {
[820]41                VirtDIR *vd = AndroidAPK_DIR::opendir(path + resources_prefix_length + 1); //+1 because we also skip '/' and start with a "relative" dir, otherwise it does not work.
[425]42                return vd;
43        }
44#endif
45
[281]46#ifdef _WIN32
47        DIRTYPE *d = wopendir(Convert::utf8ToUtf16(path).c_str());
48#else
49        DIR *d = opendir(path);
50#endif
[375]51        //log_printf("%p",d);
[298]52        if (d) return new StdioDIR(d); else return NULL;
[109]53}
54
[295]55bool StdioFileSystem::Vfexists(const char* path)
[109]56{
57        return fileExists(path);
58}
59
[820]60bool StdioFileSystem::Vdirexists(const char* path, bool is_writable)
61{
62#ifdef __ANDROID__
63        int resources_prefix_length = getAppResourcesDir().length();
64        if (strncmp(path, getAppResourcesDir().c_str(), resources_prefix_length) == 0) //it is a resources dir
65        {
66                if (is_writable)
67                        return false;
68                VirtDIR *vd = AndroidAPK_DIR::opendir(path + resources_prefix_length + 1); //+1 because we also skip '/' and start with a "relative" dir, otherwise it does not work.
69                if (vd != NULL)
70                {
71                        delete vd;
72                        return true;
73                }
74                else
75                {
76                        return false;
77                }
78        }
79#endif
80        return directoryExists(path, is_writable);
81}
82
[1328]83bool StdioFileSystem::Vdelete(const char* path)
84{
85        return removeFile(path);
86}
[820]87
[1328]88bool StdioFileSystem::Vstat(const char* path, Stat* out)
89{
[1332]90#if defined(_WIN32) && !defined(__BORLANDC__)
[1328]91        //under windows, there are a few choices of _statXX structures: 32bit, 64bit, ansi, widechar (and their corresponding _statXX() functions). For the future: ensure utf8 filenames work.
92        using stat = struct _stat64i32; //"struct" because there is also a function with the same name
93        //struct _stat64i32 info; //an alternative, simple way if one does not want to use "using" above
94#else
95        struct //if there was "using" earlier, then we cannot use "struct" in type name
96#endif
97        stat info;
[1332]98#ifdef __BORLANDC__
99    #define _stat(a,b) stat(a,b) //embarcadero uses "stat" as struct type and "stat()" as function
100#endif
[1328]101        if (_stat(path, &info) != 0) return false;
102        out->is_file = S_ISREG(info.st_mode);
103#if defined IPHONE && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
104        out->modification_time = info.st_mtimespec.tv_sec;
105#else
106        out->modification_time = info.st_mtime;
107#endif
108        return true;
109}
[820]110
[1328]111bool StdioFileSystem::Vsettime(const char* path, double timestamp)
112{
[1332]113#if defined(_WIN32) && !defined(__BORLANDC__)
[1328]114        //under windows, there are a few choices of _statXX structures: 32bit, 64bit, ansi, widechar (and their corresponding _statXX() functions). For the future: ensure utf8 filenames work.
115        using stat = struct _stat64i32; //"struct" because there is also a function with the same name
116        //struct _stat64i32 info; //an alternative, simple way if one does not want to use "using" above
117#else
118        struct //if there was "using" earlier, then we cannot use "struct" in type name
119#endif
120        stat info;
121        if (_stat(path, &info) != 0) return false;
[1332]122#ifdef __BORLANDC__ // when including <utime.h> (no "sys/"), compiles OK when using both no-underscore variants, but causes "unresolved external utime()" during linking, hence need to use both underscored variants:
123    #define utimbuf _utimbuf
124    #define utime(a,b) _utime(a,b)
125#endif
[1328]126        struct utimbuf times;
127#if defined IPHONE && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
128        times.actime = info.st_atimespec.tv_sec;
129#else
130        times.actime = info.st_atime;
131#endif
132        times.modtime = (time_t)timestamp;
133        return utime(path, &times) == 0;
134}
[820]135
[425]136#ifndef NO_STD_IN_OUT_ERR
[109]137void StdioFILE::setStdio()
138{
139        static StdioFILEDontClose si(stdin);
140        static StdioFILEDontClose so(stdout);
141        static StdioFILEDontClose se(stderr);
142        setVstdin(&si);
143        setVstdout(&so);
144        setVstderr(&se);
[425]145}
[227]146#endif
[109]147
148dirent* StdioDIR::Vreaddir()
149{
[375]150        //log_printf("Vreaddir %s",dir);
[281]151#ifdef _WIN32
[820]152        wdirent *wde = wreaddir(dir);
153        if (wde == NULL) return NULL;
[281]154        strcpy(de.d_name, Convert::wstrToUtf8(wde->d_name).c_str());
155        return &de;
156#else
[109]157        return readdir(dir);
[281]158#endif
[109]159}
Note: See TracBrowser for help on using the repository browser.