summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--configure.in2
-rw-r--r--file.c8
-rw-r--r--include/ruby/win32.h15
-rw-r--r--win32/Makefile.sub2
-rw-r--r--win32/win32.c48
6 files changed, 83 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 6510e8358c..de0a97fa7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Wed Apr 23 00:43:00 2014 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c, include/ruby/win32.h (ustatfs): implementation of
+ statfs(2) clone. [EXPERIMENTAL]
+
+ * file.c (rb_io_statfs): use above function.
+
+ * configure.in, win32/Makefile.sub (struct statfs): available.
+
Tue Apr 22 23:56:24 2014 NAKAMURA Usaku <usa@ruby-lang.org>
* file.c (rb_io_stafs): use statfs(2) if fstatfs(2) is unavailable.
diff --git a/configure.in b/configure.in
index d7a479f4a6..d44a3c5c5f 100644
--- a/configure.in
+++ b/configure.in
@@ -1059,6 +1059,8 @@ main()
ac_cv_func_clock_gettime=yes
ac_cv_func_clock_getres=yes
ac_cv_func_malloc_usable_size=no
+ ac_cv_struct_statfs=yes
+ ac_cv_member_struct_statfs_f_fstypename=yes
{ test "$target_cpu" = x64 && ac_cv_func___builtin_setjmp=no; }
AC_CHECK_TYPE([NET_LUID], [], [],
[@%:@include <windows.h>
diff --git a/file.c b/file.c
index a8ac67eb4a..8c455121de 100644
--- a/file.c
+++ b/file.c
@@ -115,6 +115,8 @@ static VALUE rb_statfs_new(const struct statfs *st);
#define unlink(p) rb_w32_uunlink(p)
#undef rename
#define rename(f, t) rb_w32_urename((f), (t))
+#undef statfs
+#define statfs(f, s) ustatfs((f), (s))
#else
#define STAT(p, s) stat((p), (s))
#endif
@@ -1118,12 +1120,16 @@ rb_io_statfs(VALUE obj)
{
rb_io_t *fptr;
struct statfs st;
+#ifndef HAVE_FSTATFS
+ VALUE path;
+#endif
GetOpenFile(obj, fptr);
#ifdef HAVE_FSTATFS
if (fstatfs(fptr->fd, &st) == -1)
#else
- if (statfs(RSTRING_PTR(fptr->pathv), &st) == -1)
+ path = rb_str_encode_ospath(fptr->pathv);
+ if (statfs(StringValueCStr(path), &st) == -1)
#endif
{
rb_sys_fail_path(fptr->pathv);
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index a6996bc95a..825b9b1cc8 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -262,6 +262,20 @@ struct ifaddrs {
#define IFF_POINTOPOINT IFF_POINTTOPOINT
#endif
+/* for ustatfs() */
+typedef uint32_t fsid_t;
+struct statfs {
+ uint32_t f_type;
+ uint64_t f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ int64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ fsid_t f_fsid;
+ char f_fstypename[MAX_PATH];
+};
+
extern DWORD rb_w32_osid(void);
extern rb_pid_t rb_w32_pipe_exec(const char *, const char *, int, int *, int *);
extern int flock(int fd, int oper);
@@ -347,6 +361,7 @@ extern int rb_w32_uaccess(const char *, int);
extern char rb_w32_fd_is_text(int);
extern int rb_w32_fstati64(int, struct stati64 *);
extern int rb_w32_dup2(int, int);
+extern int ustatfs(const char *, struct statfs *);
#ifdef __BORLANDC__
extern off_t _lseeki64(int, off_t, int);
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 7c84de184b..5a8479affb 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -699,6 +699,8 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#define SETPGRP_VOID 1
#define RSHIFT(x,y) ((x)>>(int)y)
#define HAVE_RB_FD_INIT 1
+#define HAVE_STRUCT_STATFS 1
+#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1
#define RUBY_SETJMP(env) _setjmp(env)
#define RUBY_LONGJMP(env,val) longjmp(env,val)
#define RUBY_JMP_BUF jmp_buf
diff --git a/win32/win32.c b/win32/win32.c
index 79519aab67..f8b2ff0b16 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -5865,6 +5865,54 @@ rb_w32_pipe(int fds[2])
}
/* License: Ruby's */
+int
+ustatfs(const char *path, struct statfs *buf)
+{
+ WCHAR *wpath = utf8_to_wstr(path, NULL);
+ WCHAR root[MAX_PATH], system[8];
+ DWORD serial, spc, bps, unused, total;
+ char *tmp;
+
+ if (!wpath) {
+ return -1;
+ }
+
+ if (!GetVolumePathNameW(wpath, root, sizeof(root) / sizeof(WCHAR))) {
+ free(wpath);
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+ free(wpath);
+
+ if (!GetVolumeInformationW(root, NULL, 0, &serial, NULL, NULL,
+ system, sizeof(system) / sizeof(WCHAR))) {
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+
+ if (!GetDiskFreeSpaceW(root, &spc, &bps, &unused, &total)) {
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+
+ tmp = wstr_to_filecp(system, NULL);
+ if (!tmp) {
+ return -1;
+ }
+ strlcpy(buf->f_fstypename, tmp, sizeof(buf->f_fstypename));
+ free(tmp);
+
+ buf->f_type = 0;
+ buf->f_bsize = (uint64_t)spc * bps;
+ buf->f_blocks = total;
+ buf->f_bfree = buf->f_bavail = unused;
+ buf->f_files = buf->f_ffree = 0;
+ buf->f_fsid = serial;
+
+ return 0;
+}
+
+/* License: Ruby's */
static int
console_emulator_p(void)
{