From e406eb18fcd33f1a66fef19c481c9f3ab215e086 Mon Sep 17 00:00:00 2001 From: otegami Date: Wed, 3 Sep 2025 12:41:48 +0900 Subject: [PATCH 1/4] Support for files over 2GB on Windows ## Problem File::Stat fails with RuntimeError when handling files >= 2GB on Windows. The stat operation crashes when attempting to get file statistics for large files, making it impossible to work with files over 2GB. ## Cause Windows `stat()` function uses 32-bit integers for file sizes by default, causing truncation for files >= 2GB (2^31 bytes). The regular `stat()` function and struct stat are limited to 32-bit file sizes on Windows, while Unix systems typically use 64-bit by default. ref: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions?view=msvc-170#time-type-and-file-length-type-variations-of-_stat ## Solution Use Windows 64-bit stat functions and structures: - Replace `stat()` with `_stat64()` for file statistics - Replace `fstat()` with _fstat64() for file descriptor statistics - Replace struct stat with struct `_stat64` for data structures - Define macros (STAT, LSTAT, FSTAT, STAT_STRUCT) to use 64-bit variants on Windows while keeping original functions on Unix This enables proper handling of files >= 2GB on Windows platforms while maintaining compatibility with other operating systems. --- mrbgem.rake | 1 + src/file-stat.c | 67 +++++++++++++++++++++++++++-------------------- test/file-stat.rb | 14 ++++++++++ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/mrbgem.rake b/mrbgem.rake index adf097d..a5740f0 100644 --- a/mrbgem.rake +++ b/mrbgem.rake @@ -2,6 +2,7 @@ MRuby::Gem::Specification.new('mruby-file-stat') do |spec| spec.license = 'MIT' spec.author = 'ksss ' spec.add_dependency('mruby-time') + spec.add_test_dependency('mruby-io') env = { 'CC' => "#{build.cc.command} #{build.cc.flags.join(' ')}", diff --git a/src/file-stat.c b/src/file-stat.c index fa2e000..75b86f7 100644 --- a/src/file-stat.c +++ b/src/file-stat.c @@ -101,11 +101,20 @@ # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif -#define STAT(p,s) stat(p,s) -#ifdef HAVE_LSTAT -# define LSTAT(p,s) lstat(p,s) +#if defined(_WIN32) || defined(_WIN64) +# define STAT(p,s) _stat64(p,s) +# define FSTAT(fd,s) _fstat64(fd,s) +# define LSTAT(p,s) _stat64(p,s) +# define STAT_STRUCT struct _stat64 #else -# define LSTAT(p,s) stat(p,s) +# define STAT(p,s) stat(p,s) +# define FSTAT(fd,s) fstat(fd,s) +# ifdef HAVE_LSTAT +# define LSTAT(p,s) lstat(p,s) +# else +# define LSTAT(p,s) stat(p,s) +# endif +# define STAT_STRUCT struct stat #endif #define MRB_MAX_GROUPS (65536) @@ -145,10 +154,10 @@ getegid(void) struct mrb_data_type mrb_stat_type = { "File::Stat", mrb_free }; -static struct stat * +static STAT_STRUCT * mrb_stat_alloc(mrb_state *mrb) { - return (struct stat *)mrb_malloc(mrb, sizeof(struct stat)); + return (STAT_STRUCT *)mrb_malloc(mrb, sizeof(STAT_STRUCT)); } static mrb_value @@ -156,7 +165,7 @@ file_s_lstat(mrb_state *mrb, mrb_value klass) { struct RClass *file_class; struct RClass *stat_class; - struct stat st, *ptr; + STAT_STRUCT st, *ptr; mrb_value fname, tmp; char *path; @@ -190,7 +199,7 @@ file_s_lstat(mrb_state *mrb, mrb_value klass) static mrb_value stat_initialize(mrb_state *mrb, mrb_value self) { - struct stat st, *ptr; + STAT_STRUCT st, *ptr; mrb_value fname, tmp; char *path; @@ -213,7 +222,7 @@ stat_initialize(mrb_state *mrb, mrb_value self) } } - ptr = (struct stat *)DATA_PTR(self); + ptr = (STAT_STRUCT *)DATA_PTR(self); if (ptr) { mrb_free(mrb, ptr); } @@ -246,19 +255,19 @@ stat_initialize_copy(mrb_state *mrb, mrb_value copy) } if (DATA_PTR(orig)) { - DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct stat)); + DATA_PTR(copy) = mrb_malloc(mrb, sizeof(STAT_STRUCT)); DATA_TYPE(copy) = &mrb_stat_type; - *(struct stat *)DATA_PTR(copy) = *(struct stat *)DATA_PTR(orig); + *(STAT_STRUCT *)DATA_PTR(copy) = *(STAT_STRUCT *)DATA_PTR(orig); } return copy; } -static struct stat * +static STAT_STRUCT * get_stat(mrb_state *mrb, mrb_value self) { - struct stat *st; + STAT_STRUCT *st; - st = (struct stat *)mrb_data_get_ptr(mrb, self, &mrb_stat_type); + st = (STAT_STRUCT *)mrb_data_get_ptr(mrb, self, &mrb_stat_type); if (!st) mrb_raise(mrb, E_TYPE_ERROR, "uninitialized File::Stat"); return st; } @@ -283,7 +292,7 @@ io_stat(mrb_state *mrb, mrb_value self) { struct RClass *file_class; struct RClass *stat_class; - struct stat st, *ptr; + STAT_STRUCT st, *ptr; mrb_value fileno; if (mrb_respond_to(mrb, self, mrb_intern_lit(mrb, "fileno"))) { @@ -293,7 +302,7 @@ io_stat(mrb_state *mrb, mrb_value self) mrb_raise(mrb, E_NOTIMP_ERROR, "`fileno' is not implemented"); } - if (fstat(mrb_fixnum(fileno), &st) == -1) { + if (FSTAT(mrb_fixnum(fileno), &st) == -1) { mrb_sys_fail(mrb, "fstat"); } @@ -394,7 +403,7 @@ time_at_with_sec_nsec(mrb_state *mrb, time_t sec, long nsec) } static struct timespec -stat_atimespec(const struct stat *st) +stat_atimespec(const STAT_STRUCT *st) { struct timespec ts; ts.tv_sec = st->st_atime; @@ -418,7 +427,7 @@ stat_atime(mrb_state *mrb, mrb_value self) } static struct timespec -stat_mtimespec(const struct stat *st) +stat_mtimespec(const STAT_STRUCT *st) { struct timespec ts; ts.tv_sec = st->st_mtime; @@ -442,7 +451,7 @@ stat_mtime(mrb_state *mrb, mrb_value self) } static struct timespec -stat_ctimespec(const struct stat *st) +stat_ctimespec(const STAT_STRUCT *st) { struct timespec ts; ts.tv_sec = st->st_ctime; @@ -469,7 +478,7 @@ stat_ctime(mrb_state *mrb, mrb_value self) static mrb_value stat_birthtime(mrb_state *mrb, mrb_value self) { - struct stat *st = get_stat(mrb, self); + STAT_STRUCT *st = get_stat(mrb, self); const struct timespec *ts = &st->st_birthtimespec; return time_at_with_sec_nsec(mrb, ts->tv_sec, ts->tv_nsec); } @@ -564,7 +573,7 @@ stat_grpowned_p(mrb_state *mrb, mrb_value self) static mrb_value stat_readable_p(mrb_state *mrb, mrb_value self) { - struct stat *st; + STAT_STRUCT *st; #ifdef USE_GETEUID if (geteuid() == 0) return mrb_true_value(); @@ -588,7 +597,7 @@ stat_readable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_readable_real_p(mrb_state *mrb, mrb_value self) { - struct stat *st; + STAT_STRUCT *st; #ifdef USE_GETEUID if (getuid() == 0) @@ -613,7 +622,7 @@ static mrb_value stat_world_readable_p(mrb_state *mrb, mrb_value self) { #ifdef S_IROTH - struct stat *st = get_stat(mrb, self); + STAT_STRUCT *st = get_stat(mrb, self); if ((st->st_mode & (S_IROTH)) == S_IROTH) { return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } @@ -629,7 +638,7 @@ stat_world_readable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_writable_p(mrb_state *mrb, mrb_value self) { - struct stat *st; + STAT_STRUCT *st; #ifdef USE_GETEUID if (geteuid() == 0) @@ -654,7 +663,7 @@ stat_writable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_writable_real_p(mrb_state *mrb, mrb_value self) { - struct stat *st; + STAT_STRUCT *st; #ifdef USE_GETEUID if (getuid() == 0) @@ -679,7 +688,7 @@ static mrb_value stat_world_writable_p(mrb_state *mrb, mrb_value self) { #ifdef S_IWOTH - struct stat *st = get_stat(mrb, self); + STAT_STRUCT *st = get_stat(mrb, self); if ((st->st_mode & (S_IWOTH)) == S_IWOTH) { return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } @@ -694,7 +703,7 @@ stat_world_writable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_executable_p(mrb_state *mrb, mrb_value self) { - struct stat *st = get_stat(mrb, self); + STAT_STRUCT *st = get_stat(mrb, self); #ifdef USE_GETEUID if (geteuid() == 0) { @@ -719,7 +728,7 @@ stat_executable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_executable_real_p(mrb_state *mrb, mrb_value self) { - struct stat *st = get_stat(mrb, self); + STAT_STRUCT *st = get_stat(mrb, self); #ifdef USE_GETEUID if (getuid() == 0) @@ -836,7 +845,7 @@ stat_sticky_p(mrb_state *mrb, mrb_value self) static mrb_value stat_ftype(mrb_state *mrb, mrb_value self) { - struct stat *st = get_stat(mrb, self); + STAT_STRUCT *st = get_stat(mrb, self); const char *t; if (S_ISREG(st->st_mode)) { diff --git a/test/file-stat.rb b/test/file-stat.rb index 28d871e..18d0957 100644 --- a/test/file-stat.rb +++ b/test/file-stat.rb @@ -301,6 +301,20 @@ def chmod(mode, path) assert_true 0 < stat.size? end +assert 'File::Stat#size with large file (2GB)' do + large_file = "test_large_file.tmp" + target_size = 2**31 # 2GB + begin + File.open(large_file, 'wb') do |f| + (2**19).times { f << "\0" * 4096 } + end + stat = File::Stat.new(large_file) + assert_equal target_size, stat.size + ensure + File.delete(large_file) if File.exist?(large_file) + end +end + assert 'File::Stat#owned?' do stat = File::Stat.new('README.md') assert_true stat.owned? From 34be575c3d0bd50ae1edee6588af4c18d1a5f0ec Mon Sep 17 00:00:00 2001 From: otegami Date: Wed, 3 Sep 2025 16:52:44 +0900 Subject: [PATCH 2/4] Replace STAT_STRUCT macro with mrb_stat struct name Improve code consistency by replacing the STAT_STRUCT macro with a more conventional mrb_stat struct name approach: - Windows: mrb_stat -> _stat64 (for 64-bit file support) - Unix/Linux: mrb_stat -> stat (standard struct) --- src/file-stat.c | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/file-stat.c b/src/file-stat.c index 75b86f7..d466eeb 100644 --- a/src/file-stat.c +++ b/src/file-stat.c @@ -105,7 +105,7 @@ # define STAT(p,s) _stat64(p,s) # define FSTAT(fd,s) _fstat64(fd,s) # define LSTAT(p,s) _stat64(p,s) -# define STAT_STRUCT struct _stat64 +# define mrb_stat _stat64 #else # define STAT(p,s) stat(p,s) # define FSTAT(fd,s) fstat(fd,s) @@ -114,7 +114,7 @@ # else # define LSTAT(p,s) stat(p,s) # endif -# define STAT_STRUCT struct stat +# define mrb_stat stat #endif #define MRB_MAX_GROUPS (65536) @@ -154,10 +154,10 @@ getegid(void) struct mrb_data_type mrb_stat_type = { "File::Stat", mrb_free }; -static STAT_STRUCT * +static struct mrb_stat * mrb_stat_alloc(mrb_state *mrb) { - return (STAT_STRUCT *)mrb_malloc(mrb, sizeof(STAT_STRUCT)); + return (struct mrb_stat *)mrb_malloc(mrb, sizeof(struct mrb_stat)); } static mrb_value @@ -165,7 +165,7 @@ file_s_lstat(mrb_state *mrb, mrb_value klass) { struct RClass *file_class; struct RClass *stat_class; - STAT_STRUCT st, *ptr; + struct mrb_stat st, *ptr; mrb_value fname, tmp; char *path; @@ -199,7 +199,7 @@ file_s_lstat(mrb_state *mrb, mrb_value klass) static mrb_value stat_initialize(mrb_state *mrb, mrb_value self) { - STAT_STRUCT st, *ptr; + struct mrb_stat st, *ptr; mrb_value fname, tmp; char *path; @@ -222,7 +222,7 @@ stat_initialize(mrb_state *mrb, mrb_value self) } } - ptr = (STAT_STRUCT *)DATA_PTR(self); + ptr = (struct mrb_stat *)DATA_PTR(self); if (ptr) { mrb_free(mrb, ptr); } @@ -255,19 +255,19 @@ stat_initialize_copy(mrb_state *mrb, mrb_value copy) } if (DATA_PTR(orig)) { - DATA_PTR(copy) = mrb_malloc(mrb, sizeof(STAT_STRUCT)); + DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct mrb_stat)); DATA_TYPE(copy) = &mrb_stat_type; - *(STAT_STRUCT *)DATA_PTR(copy) = *(STAT_STRUCT *)DATA_PTR(orig); + *(struct mrb_stat *)DATA_PTR(copy) = *(struct mrb_stat *)DATA_PTR(orig); } return copy; } -static STAT_STRUCT * +static struct mrb_stat * get_stat(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st; + struct mrb_stat *st; - st = (STAT_STRUCT *)mrb_data_get_ptr(mrb, self, &mrb_stat_type); + st = (struct mrb_stat *)mrb_data_get_ptr(mrb, self, &mrb_stat_type); if (!st) mrb_raise(mrb, E_TYPE_ERROR, "uninitialized File::Stat"); return st; } @@ -292,7 +292,7 @@ io_stat(mrb_state *mrb, mrb_value self) { struct RClass *file_class; struct RClass *stat_class; - STAT_STRUCT st, *ptr; + struct mrb_stat st, *ptr; mrb_value fileno; if (mrb_respond_to(mrb, self, mrb_intern_lit(mrb, "fileno"))) { @@ -403,7 +403,7 @@ time_at_with_sec_nsec(mrb_state *mrb, time_t sec, long nsec) } static struct timespec -stat_atimespec(const STAT_STRUCT *st) +stat_atimespec(const struct mrb_stat *st) { struct timespec ts; ts.tv_sec = st->st_atime; @@ -427,7 +427,7 @@ stat_atime(mrb_state *mrb, mrb_value self) } static struct timespec -stat_mtimespec(const STAT_STRUCT *st) +stat_mtimespec(const struct mrb_stat *st) { struct timespec ts; ts.tv_sec = st->st_mtime; @@ -451,7 +451,7 @@ stat_mtime(mrb_state *mrb, mrb_value self) } static struct timespec -stat_ctimespec(const STAT_STRUCT *st) +stat_ctimespec(const struct mrb_stat *st) { struct timespec ts; ts.tv_sec = st->st_ctime; @@ -478,7 +478,7 @@ stat_ctime(mrb_state *mrb, mrb_value self) static mrb_value stat_birthtime(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st = get_stat(mrb, self); + struct mrb_stat *st = get_stat(mrb, self); const struct timespec *ts = &st->st_birthtimespec; return time_at_with_sec_nsec(mrb, ts->tv_sec, ts->tv_nsec); } @@ -573,7 +573,7 @@ stat_grpowned_p(mrb_state *mrb, mrb_value self) static mrb_value stat_readable_p(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st; + struct mrb_stat *st; #ifdef USE_GETEUID if (geteuid() == 0) return mrb_true_value(); @@ -597,7 +597,7 @@ stat_readable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_readable_real_p(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st; + struct mrb_stat *st; #ifdef USE_GETEUID if (getuid() == 0) @@ -622,7 +622,7 @@ static mrb_value stat_world_readable_p(mrb_state *mrb, mrb_value self) { #ifdef S_IROTH - STAT_STRUCT *st = get_stat(mrb, self); + struct mrb_stat *st = get_stat(mrb, self); if ((st->st_mode & (S_IROTH)) == S_IROTH) { return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } @@ -638,7 +638,7 @@ stat_world_readable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_writable_p(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st; + struct mrb_stat *st; #ifdef USE_GETEUID if (geteuid() == 0) @@ -663,7 +663,7 @@ stat_writable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_writable_real_p(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st; + struct mrb_stat *st; #ifdef USE_GETEUID if (getuid() == 0) @@ -688,7 +688,7 @@ static mrb_value stat_world_writable_p(mrb_state *mrb, mrb_value self) { #ifdef S_IWOTH - STAT_STRUCT *st = get_stat(mrb, self); + struct mrb_stat *st = get_stat(mrb, self); if ((st->st_mode & (S_IWOTH)) == S_IWOTH) { return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } @@ -703,7 +703,7 @@ stat_world_writable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_executable_p(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st = get_stat(mrb, self); + struct mrb_stat *st = get_stat(mrb, self); #ifdef USE_GETEUID if (geteuid() == 0) { @@ -728,7 +728,7 @@ stat_executable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_executable_real_p(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st = get_stat(mrb, self); + struct mrb_stat *st = get_stat(mrb, self); #ifdef USE_GETEUID if (getuid() == 0) @@ -845,7 +845,7 @@ stat_sticky_p(mrb_state *mrb, mrb_value self) static mrb_value stat_ftype(mrb_state *mrb, mrb_value self) { - STAT_STRUCT *st = get_stat(mrb, self); + struct mrb_stat *st = get_stat(mrb, self); const char *t; if (S_ISREG(st->st_mode)) { From e15ed5b1aae1cfd6d2e106b160a79ab19fdbe0ea Mon Sep 17 00:00:00 2001 From: otegami Date: Wed, 3 Sep 2025 17:04:45 +0900 Subject: [PATCH 3/4] Use target_size directly in large file test for readability --- test/file-stat.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/file-stat.rb b/test/file-stat.rb index 18d0957..469c066 100644 --- a/test/file-stat.rb +++ b/test/file-stat.rb @@ -306,7 +306,8 @@ def chmod(mode, path) target_size = 2**31 # 2GB begin File.open(large_file, 'wb') do |f| - (2**19).times { f << "\0" * 4096 } + f.seek(target_size - 1) + f.write("\0") end stat = File::Stat.new(large_file) assert_equal target_size, stat.size From 7a7009ee32a4cd0f634b7098fb795789ec85e609 Mon Sep 17 00:00:00 2001 From: otegami Date: Thu, 4 Sep 2025 15:03:39 +0900 Subject: [PATCH 4/4] Use typedef instead of define for type aliasing --- src/file-stat.c | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/file-stat.c b/src/file-stat.c index d466eeb..60e51cd 100644 --- a/src/file-stat.c +++ b/src/file-stat.c @@ -105,7 +105,7 @@ # define STAT(p,s) _stat64(p,s) # define FSTAT(fd,s) _fstat64(fd,s) # define LSTAT(p,s) _stat64(p,s) -# define mrb_stat _stat64 + typedef struct _stat64 mrb_stat; #else # define STAT(p,s) stat(p,s) # define FSTAT(fd,s) fstat(fd,s) @@ -114,7 +114,7 @@ # else # define LSTAT(p,s) stat(p,s) # endif -# define mrb_stat stat + typedef struct stat mrb_stat; #endif #define MRB_MAX_GROUPS (65536) @@ -154,10 +154,10 @@ getegid(void) struct mrb_data_type mrb_stat_type = { "File::Stat", mrb_free }; -static struct mrb_stat * +static mrb_stat * mrb_stat_alloc(mrb_state *mrb) { - return (struct mrb_stat *)mrb_malloc(mrb, sizeof(struct mrb_stat)); + return (mrb_stat *)mrb_malloc(mrb, sizeof(mrb_stat)); } static mrb_value @@ -165,7 +165,7 @@ file_s_lstat(mrb_state *mrb, mrb_value klass) { struct RClass *file_class; struct RClass *stat_class; - struct mrb_stat st, *ptr; + mrb_stat st, *ptr; mrb_value fname, tmp; char *path; @@ -199,7 +199,7 @@ file_s_lstat(mrb_state *mrb, mrb_value klass) static mrb_value stat_initialize(mrb_state *mrb, mrb_value self) { - struct mrb_stat st, *ptr; + mrb_stat st, *ptr; mrb_value fname, tmp; char *path; @@ -222,7 +222,7 @@ stat_initialize(mrb_state *mrb, mrb_value self) } } - ptr = (struct mrb_stat *)DATA_PTR(self); + ptr = (mrb_stat *)DATA_PTR(self); if (ptr) { mrb_free(mrb, ptr); } @@ -255,19 +255,19 @@ stat_initialize_copy(mrb_state *mrb, mrb_value copy) } if (DATA_PTR(orig)) { - DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct mrb_stat)); + DATA_PTR(copy) = mrb_malloc(mrb, sizeof(mrb_stat)); DATA_TYPE(copy) = &mrb_stat_type; - *(struct mrb_stat *)DATA_PTR(copy) = *(struct mrb_stat *)DATA_PTR(orig); + *(mrb_stat *)DATA_PTR(copy) = *(mrb_stat *)DATA_PTR(orig); } return copy; } -static struct mrb_stat * +static mrb_stat * get_stat(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st; + mrb_stat *st; - st = (struct mrb_stat *)mrb_data_get_ptr(mrb, self, &mrb_stat_type); + st = (mrb_stat *)mrb_data_get_ptr(mrb, self, &mrb_stat_type); if (!st) mrb_raise(mrb, E_TYPE_ERROR, "uninitialized File::Stat"); return st; } @@ -292,7 +292,7 @@ io_stat(mrb_state *mrb, mrb_value self) { struct RClass *file_class; struct RClass *stat_class; - struct mrb_stat st, *ptr; + mrb_stat st, *ptr; mrb_value fileno; if (mrb_respond_to(mrb, self, mrb_intern_lit(mrb, "fileno"))) { @@ -403,7 +403,7 @@ time_at_with_sec_nsec(mrb_state *mrb, time_t sec, long nsec) } static struct timespec -stat_atimespec(const struct mrb_stat *st) +stat_atimespec(const mrb_stat *st) { struct timespec ts; ts.tv_sec = st->st_atime; @@ -427,7 +427,7 @@ stat_atime(mrb_state *mrb, mrb_value self) } static struct timespec -stat_mtimespec(const struct mrb_stat *st) +stat_mtimespec(const mrb_stat *st) { struct timespec ts; ts.tv_sec = st->st_mtime; @@ -451,7 +451,7 @@ stat_mtime(mrb_state *mrb, mrb_value self) } static struct timespec -stat_ctimespec(const struct mrb_stat *st) +stat_ctimespec(const mrb_stat *st) { struct timespec ts; ts.tv_sec = st->st_ctime; @@ -478,7 +478,7 @@ stat_ctime(mrb_state *mrb, mrb_value self) static mrb_value stat_birthtime(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st = get_stat(mrb, self); + mrb_stat *st = get_stat(mrb, self); const struct timespec *ts = &st->st_birthtimespec; return time_at_with_sec_nsec(mrb, ts->tv_sec, ts->tv_nsec); } @@ -573,7 +573,7 @@ stat_grpowned_p(mrb_state *mrb, mrb_value self) static mrb_value stat_readable_p(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st; + mrb_stat *st; #ifdef USE_GETEUID if (geteuid() == 0) return mrb_true_value(); @@ -597,7 +597,7 @@ stat_readable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_readable_real_p(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st; + mrb_stat *st; #ifdef USE_GETEUID if (getuid() == 0) @@ -622,7 +622,7 @@ static mrb_value stat_world_readable_p(mrb_state *mrb, mrb_value self) { #ifdef S_IROTH - struct mrb_stat *st = get_stat(mrb, self); + mrb_stat *st = get_stat(mrb, self); if ((st->st_mode & (S_IROTH)) == S_IROTH) { return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } @@ -638,7 +638,7 @@ stat_world_readable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_writable_p(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st; + mrb_stat *st; #ifdef USE_GETEUID if (geteuid() == 0) @@ -663,7 +663,7 @@ stat_writable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_writable_real_p(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st; + mrb_stat *st; #ifdef USE_GETEUID if (getuid() == 0) @@ -688,7 +688,7 @@ static mrb_value stat_world_writable_p(mrb_state *mrb, mrb_value self) { #ifdef S_IWOTH - struct mrb_stat *st = get_stat(mrb, self); + mrb_stat *st = get_stat(mrb, self); if ((st->st_mode & (S_IWOTH)) == S_IWOTH) { return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } @@ -703,7 +703,7 @@ stat_world_writable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_executable_p(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st = get_stat(mrb, self); + mrb_stat *st = get_stat(mrb, self); #ifdef USE_GETEUID if (geteuid() == 0) { @@ -728,7 +728,7 @@ stat_executable_p(mrb_state *mrb, mrb_value self) static mrb_value stat_executable_real_p(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st = get_stat(mrb, self); + mrb_stat *st = get_stat(mrb, self); #ifdef USE_GETEUID if (getuid() == 0) @@ -845,7 +845,7 @@ stat_sticky_p(mrb_state *mrb, mrb_value self) static mrb_value stat_ftype(mrb_state *mrb, mrb_value self) { - struct mrb_stat *st = get_stat(mrb, self); + mrb_stat *st = get_stat(mrb, self); const char *t; if (S_ISREG(st->st_mode)) {