[#23843] st_dev by stat() != st_dev by fstat() in windows — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
山本です。
6 messages
2004/07/01
[#23847] Re: st_dev by stat() != st_dev by fstat() in windows
— "U.Nakamura" <usa@...>
2004/07/01
こんにちは、なかむら(う)です。
[#23855] Are these comittable? — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
山本です。
12 messages
2004/07/04
[#23856] Re: Are these comittable?
— nobu.nakada@...
2004/07/04
なかだです。
[#23871] syntax error — WATANABE Hirofumi <eban@...>
わたなべです。
5 messages
2004/07/09
[#23876] cgi, cgi/session — 堀川 久 <vzw00011@...>
こんにちは。
10 messages
2004/07/10
[#23890] Re: cgi, cgi/session
— matz@... (Yukihiro Matsumoto)
2004/07/14
まつもと ゆきひろです
[#23884] Ruby 1.8.2 preview1にむけて — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
34 messages
2004/07/13
[#23889] Re: Ruby 1.8.2 preview1にむけて
— "NAKAMURA, Hiroshi" <nakahiro@...>
2004/07/14
なひです。
[#23917] Re: Ruby 1.8.2 preview1にむけて
— "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
2004/07/16
山本です。
[#23920] Re: Ruby 1.8.2 preview1にむけて
— "NAKAMURA, Hiroshi" <nakahiro@...>
2004/07/16
なひです。
[#23921] Re: Ruby 1.8.2 preview1にむけて
— "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
2004/07/16
山本です。レスが遅れてすみません。
[#23927] Re: Ruby 1.8.2 preview1にむけて
— "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
2004/07/16
山本です。
[#23932] Re: Ruby 1.8.2 preview1にむけて
— "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
2004/07/16
山本です。
[#23936] Re: Ruby 1.8.2 preview1にむけて
— "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
2004/07/17
山本です。進展がありました。どうも、通常設定されている
[#23937] Re: Ruby 1.8.2 preview1にむけて
— "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
2004/07/17
山本です。
[#23939] Re: Ruby 1.8.2 preview1にむけて
— GOTOU Yuuzou <gotoyuzo@...>
2004/07/17
In message <20040717191809.EF0AA070.ocean@m2.ccsnet.ne.jp>,
[#23922] ruby 1.8.2 preview1 — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
27 messages
2004/07/16
[#23945] Re: ruby 1.8.2 preview1
— akira yamada <akira@...>
2004/07/21
1.8.2または1.8.2-preview2の公開時期について
[#23967] WEBrick::HTTPUtils.escape and URI.escape — Tanaka Akira <akr@...17n.org>
ついでに尋ねますが、WEBrick::HTTPUtils.escape か URI.escape で、
5 messages
2004/07/26
[#23969] Re: WEBrick::HTTPUtils.escape and URI.escape
— Tanaka Akira <akr@...17n.org>
2004/07/26
In article <20040726.145658.35017253.gotoyuzo@sawara.does.notwork.org>,
[#23973] 引数の上書きとsuper — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
5 messages
2004/07/27
[#23991] 1.8.2-preview2? — akira yamada / やまだあきら <akira@...>
9 messages
2004/07/29
[#23995] String#each -> String#each_char — Shugo Maeda <shugo@...>
前田です。
27 messages
2004/07/30
[#23996] Re: String#each -> String#each_char
— matz@... (Yukihiro Matsumoto)
2004/07/30
まつもと ゆきひろです
[#23997] Re: String#each -> String#each_char
— "U.Nakamura" <usa@...>
2004/07/30
こんにちは、なかむら(う)です。
[#23999] Re: String#each -> String#each_char
— matz@... (Yukihiro Matsumoto)
2004/07/30
まつもと ゆきひろです
[#24000] Re: String#each -> String#each_char
— "U.Nakamura" <usa@...>
2004/07/30
こんにちは、なかむら(う)です。
[#24005] Re: String#each -> String#each_char
— Minero Aoki <aamine@...>
2004/07/31
青木です。
[#24012] Re: String#each -> String#each_char
— Shugo Maeda <shugo@...>
2004/08/01
前田です。
[#24014] Re: String#each -> String#each_char
— Minero Aoki <aamine@...>
2004/08/02
青木です。
[#24020] Re: String#each -> String#each_char
— Shugo Maeda <shugo@...>
2004/08/05
前田です。
[#24022] Re: String#each -> String#each_char
— Minero Aoki <aamine@...>
2004/08/05
青木です。
[ruby-dev:23853] Re: st_dev by stat() != st_dev by fstat() in windows
From:
"H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
Date:
2004-07-02 04:13:58 UTC
List:
ruby-dev #23853
山本です。
"U.Nakamura" <usa@garbagecollect.jp> wrote:
(2004/07/02 09:56)
>というわけで、とりあえずは
> 「st_devとst_inoを正しく設定しないといけないの?」
>というのが問題で、速度などは二の次かなーと思います。
個人的には、両方とも0でいいような気がします。Windows だと、
ファイルハンドルに対してしか同一性を保証できないようなので・・・
>まあ、Cygwinの実装はそれなりに参考になると思います。
http://www.kaimei.org/note/mag/in_cyg.html でしょうか。
st_ino の取得にはかなり複雑な方法が必要なようですね・・・
>st_devとst_inoを完璧に設定するよりは簡単じゃないかなあ。
ああ、IOのインスタンスメソッドにすれば簡単ですね。
(Unix では st_dev, st_ino を使って、Windows でもファイルが開きっぱなしなので
GetFileInformationByHandle で問題なし。他の環境では NotImplementedError ?)
最初、stat()のようにパスから比較するのをイメージしていました。
次の点が不完全ですが、とりあえず stat() fstat() を自前で実装してみました。
- UNC で動くか確かめてない
- ファイルサイズが32bit(st_size が符号なしなら簡単ですが、そういった保証が得られませんでした)
- とりあえず st_dev, st_ino は 0
- IF_SOCK は未実装
Tietew さんのように struct stat を差し替えようと思いましたが、組み込み ruby で
アプリ側の struct stat と異なってもいいのか自信がなかったので、とりあえず 32bit にしました。
# 以前ファイルの属性を得るのに、"FindFirstFile" と、"CreateFile + GetFileSizeなど"
# を比べて、CreateFileは相当重かった記憶があるのですが、なぜか全然遅くなりませんでした。
# やりかたがまずかったのか、もしくはWin98では重いのかもしれません。
Index: win32.h
===================================================================
RCS file: /var/cvs/src/ruby/win32/win32.h,v
retrieving revision 1.51
diff -u -w -b -p -r1.51 win32.h
--- win32.h 19 Feb 2004 09:08:23 -0000 1.51
+++ win32.h 2 Jul 2004 03:42:22 -0000
@@ -113,12 +113,12 @@ extern "C++" {
#define write(h, b, l) _write(h, b, l)
#define _open _sopen
#define sopen _sopen
-#undef fstat
-#define fstat(fd,st) rb_w32_fstat(fd,st)
#endif
#define fsync(h) _commit(h)
#undef stat
#define stat(path,st) rb_w32_stat(path,st)
+#undef fstat
+#define fstat(fd,st) rb_w32_fstat(fd,st)
#undef execv
#define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv)
Index: win32.c
===================================================================
RCS file: /var/cvs/src/ruby/win32/win32.c,v
retrieving revision 1.117
diff -u -w -b -p -r1.117 win32.c
--- win32.c 21 Jun 2004 00:27:39 -0000 1.117
+++ win32.c 2 Jul 2004 03:41:58 -0000
@@ -2725,23 +2725,80 @@ isUNCRoot(const char *path)
return 0;
}
-#ifdef __BORLANDC__
-#undef fstat
+static time_t
+filetime_to_unixtime(const FILETIME *ft)
+{
+ FILETIME loc;
+ SYSTEMTIME st;
+ struct tm tm;
+ time_t t;
+
+ if (!FileTimeToLocalFileTime(ft, &loc)) {
+ return 0;
+ }
+ if (!FileTimeToSystemTime(&loc, &st)) {
+ return 0;
+ }
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = st.wYear - 1900;
+ tm.tm_mon = st.wMonth - 1;
+ tm.tm_mday = st.wDay;
+ tm.tm_hour = st.wHour;
+ tm.tm_min = st.wMinute;
+ tm.tm_sec = st.wSecond;
+ t = mktime(&tm);
+ return t == -1 ? 0 : t;
+}
+
int
-rb_w32_fstat(int fd, struct stat *st)
+os_stat(HANDLE h, struct stat *st)
{
BY_HANDLE_FILE_INFORMATION info;
- int ret = fstat(fd, st);
- if (ret) return ret;
- st->st_mode &= ~(S_IWGRP | S_IWOTH);
- if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &info) &&
- !(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
- st->st_mode |= S_IWUSR;
+ memset(st, 0, sizeof(struct stat));
+ switch (GetFileType(h)) {
+ case FILE_TYPE_DISK:
+ if (!GetFileInformationByHandle(h, &info)) {
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+ st->st_mode = S_IREAD;
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ st->st_mode |= (S_IFDIR | S_IWRITE | S_IWUSR | S_IEXEC);
+ else if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ st->st_mode |= (S_IFREG);
+ else
+ st->st_mode |= (S_IFREG | S_IWRITE | S_IWUSR);
+ st->st_nlink = info.nNumberOfLinks;
+// st->st_dev = st->st_rdev = info.dwVolumeSerialNumber;
+ st->st_atime = filetime_to_unixtime(&info.ftLastAccessTime);
+ st->st_mtime = filetime_to_unixtime(&info.ftLastWriteTime);
+ st->st_ctime = filetime_to_unixtime(&info.ftCreationTime);
+ st->st_size = info.nFileSizeLow;
+// st->st_size = info.nFileSizeHigh;
+// st->st_size << 32;
+// st->st_size += info.nFileSizeLow;
+ break;
+ case FILE_TYPE_CHAR:
+ st->st_mode = S_IFCHR;
+ break;
+ case FILE_TYPE_PIPE:
+ st->st_mode = S_IFIFO;
+ break;
+ }
+ return 0;
}
- return ret;
+
+int
+rb_w32_fstat(int fd, struct stat *st)
+{
+ long h = _get_osfhandle(fd);
+
+ if (h < 0)
+ return -1;
+ else
+ return os_stat((HANDLE)h, st);
}
-#endif
int
rb_w32_stat(const char *path, struct stat *st)
@@ -2750,6 +2807,7 @@ rb_w32_stat(const char *path, struct sta
char *buf1, *s, *end;
int len;
int ret;
+ HANDLE h;
if (!path || !st) {
errno = EFAULT;
@@ -2778,9 +2836,36 @@ rb_w32_stat(const char *path, struct sta
} else if (*end == '\\' || (buf1 + 1 == end && *end == ':'))
strcat(buf1, ".");
- ret = stat(buf1, st);
- if (ret == 0) {
- st->st_mode &= ~(S_IWGRP | S_IWOTH);
+ h = CreateFile(
+ buf1,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+ if (h == INVALID_HANDLE_VALUE) {
+ errno = map_errno(GetLastError());
+ return -1;
+ }
+ ret = os_stat(h, st);
+ CloseHandle(h);
+
+ if (ret == 0 && S_ISREG(st->st_mode)) {
+ end = buf1 + strlen(buf1);
+ while (buf1 < end) {
+ end = CharPrev(buf1, end);
+ if (*end == '.') {
+ if ((strcmpi(end, ".bat") == 0) ||
+ (strcmpi(end, ".cmd") == 0) ||
+ (strcmpi(end, ".com") == 0) ||
+ (strcmpi(end, ".exe") == 0)) {
+ st->st_mode |= S_IEXEC;
+ }
+ break;
+ }
+ }
}
return ret;
}