source: EcnlProtoTool/trunk/mrbgems/mruby-io/src/file_test.c@ 279

Last change on this file since 279 was 279, checked in by coas-nagasima, 7 years ago

ファイルを追加、更新。

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 7.9 KB
Line 
1/*
2** file.c - File class
3*/
4
5#include "mruby.h"
6#include "mruby/class.h"
7#include "mruby/data.h"
8#include "mruby/string.h"
9#include "mruby/ext/io.h"
10
11#if MRUBY_RELEASE_NO < 10000
12#include "error.h"
13#else
14#include "mruby/error.h"
15#endif
16
17#include <sys/types.h>
18#include <sys/stat.h>
19
20#if defined(_WIN32) || defined(_WIN64)
21 #define LSTAT stat
22 #include <winsock.h>
23#else
24 //#define LSTAT lstat
25 #define LSTAT stat
26 #include <sys/file.h>
27 #include <sys/param.h>
28 #include <sys/wait.h>
29 #include <libgen.h>
30 #include <pwd.h>
31 #include <unistd.h>
32#endif
33
34#include <fcntl.h>
35
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41extern struct mrb_data_type mrb_io_type;
42
43static int
44mrb_stat0(mrb_state *mrb, mrb_value obj, struct stat *st, int do_lstat)
45{
46 mrb_value tmp;
47 mrb_value io_klass, str_klass;
48
49 io_klass = mrb_obj_value(mrb_class_get(mrb, "IO"));
50 str_klass = mrb_obj_value(mrb_class_get(mrb, "String"));
51
52 tmp = mrb_funcall(mrb, obj, "is_a?", 1, io_klass);
53 if (mrb_test(tmp)) {
54 struct mrb_io *fptr;
55 fptr = (struct mrb_io *)mrb_get_datatype(mrb, obj, &mrb_io_type);
56
57 if (fptr && fptr->fd >= 0) {
58 return fstat(fptr->fd, st);
59 }
60
61 mrb_raise(mrb, E_IO_ERROR, "closed stream");
62 return -1;
63 }
64
65 tmp = mrb_funcall(mrb, obj, "is_a?", 1, str_klass);
66 if (mrb_test(tmp)) {
67 if (do_lstat) {
68 return LSTAT(mrb_str_to_cstr(mrb, obj), st);
69 } else {
70 return stat(mrb_str_to_cstr(mrb, obj), st);
71 }
72 }
73
74 return -1;
75}
76
77static int
78mrb_stat(mrb_state *mrb, mrb_value obj, struct stat *st)
79{
80 return mrb_stat0(mrb, obj, st, 0);
81}
82
83static int
84mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
85{
86 return mrb_stat0(mrb, obj, st, 1);
87}
88
89/*
90 * Document-method: directory?
91 *
92 * call-seq:
93 * File.directory?(file_name) -> true or false
94 *
95 * Returns <code>true</code> if the named file is a directory,
96 * or a symlink that points at a directory, and <code>false</code>
97 * otherwise.
98 *
99 * File.directory?(".")
100 */
101
102mrb_value
103mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
104{
105#ifndef S_ISDIR
106# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
107#endif
108
109 struct stat st;
110 mrb_value obj;
111
112 mrb_get_args(mrb, "o", &obj);
113
114 if (mrb_stat(mrb, obj, &st) < 0)
115 return mrb_false_value();
116 if (S_ISDIR(st.st_mode))
117 return mrb_true_value();
118
119 return mrb_false_value();
120}
121
122/*
123 * call-seq:
124 * File.pipe?(file_name) -> true or false
125 *
126 * Returns <code>true</code> if the named file is a pipe.
127 */
128
129mrb_value
130mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
131{
132#if defined(_WIN32) || defined(_WIN64)
133 mrb_raise(mrb, E_NOTIMP_ERROR, "pipe is not supported on this platform");
134#else
135#ifdef S_IFIFO
136# ifndef S_ISFIFO
137# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
138# endif
139
140 struct stat st;
141 mrb_value obj;
142
143 mrb_get_args(mrb, "o", &obj);
144
145 if (mrb_stat(mrb, obj, &st) < 0)
146 return mrb_false_value();
147 if (S_ISFIFO(st.st_mode))
148 return mrb_true_value();
149
150#endif
151 return mrb_false_value();
152#endif
153}
154
155/*
156 * call-seq:
157 * File.symlink?(file_name) -> true or false
158 *
159 * Returns <code>true</code> if the named file is a symbolic link.
160 */
161
162mrb_value
163mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
164{
165#if defined(_WIN32) || defined(_WIN64)
166 mrb_raise(mrb, E_NOTIMP_ERROR, "symlink is not supported on this platform");
167#else
168#ifndef S_ISLNK
169# ifdef _S_ISLNK
170# define S_ISLNK(m) _S_ISLNK(m)
171# else
172# ifdef _S_IFLNK
173# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
174# else
175# ifdef S_IFLNK
176# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
177# endif
178# endif
179# endif
180#endif
181
182#ifdef S_ISLNK
183 struct stat st;
184 mrb_value obj;
185
186 mrb_get_args(mrb, "o", &obj);
187
188 if (mrb_lstat(mrb, obj, &st) == -1)
189 return mrb_false_value();
190 if (S_ISLNK(st.st_mode))
191 return mrb_true_value();
192#endif
193
194 return mrb_false_value();
195#endif
196}
197
198/*
199 * call-seq:
200 * File.socket?(file_name) -> true or false
201 *
202 * Returns <code>true</code> if the named file is a socket.
203 */
204
205mrb_value
206mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
207{
208#if defined(_WIN32) || defined(_WIN64)
209 mrb_raise(mrb, E_NOTIMP_ERROR, "socket is not supported on this platform");
210#else
211#ifndef S_ISSOCK
212# ifdef _S_ISSOCK
213# define S_ISSOCK(m) _S_ISSOCK(m)
214# else
215# ifdef _S_IFSOCK
216# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
217# else
218# ifdef S_IFSOCK
219# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
220# endif
221# endif
222# endif
223#endif
224
225#ifdef S_ISSOCK
226 struct stat st;
227 mrb_value obj;
228
229 mrb_get_args(mrb, "o", &obj);
230
231 if (mrb_stat(mrb, obj, &st) < 0)
232 return mrb_false_value();
233 if (S_ISSOCK(st.st_mode))
234 return mrb_true_value();
235#endif
236
237 return mrb_false_value();
238#endif
239}
240
241/*
242 * call-seq:
243 * File.exist?(file_name) -> true or false
244 * File.exists?(file_name) -> true or false
245 *
246 * Return <code>true</code> if the named file exists.
247 */
248
249mrb_value
250mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
251{
252 struct stat st;
253 mrb_value obj;
254
255 mrb_get_args(mrb, "o", &obj);
256 if (mrb_stat(mrb, obj, &st) < 0)
257 return mrb_false_value();
258
259 return mrb_true_value();
260}
261
262/*
263 * call-seq:
264 * File.file?(file_name) -> true or false
265 *
266 * Returns <code>true</code> if the named file exists and is a
267 * regular file.
268 */
269
270mrb_value
271mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
272{
273#ifndef S_ISREG
274# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
275#endif
276
277 struct stat st;
278 mrb_value obj;
279
280 mrb_get_args(mrb, "o", &obj);
281
282 if (mrb_stat(mrb, obj, &st) < 0)
283 return mrb_false_value();
284 if (S_ISREG(st.st_mode))
285 return mrb_true_value();
286
287 return mrb_false_value();
288}
289
290/*
291 * call-seq:
292 * File.zero?(file_name) -> true or false
293 *
294 * Returns <code>true</code> if the named file exists and has
295 * a zero size.
296 */
297
298mrb_value
299mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
300{
301 struct stat st;
302 mrb_value obj;
303
304 mrb_get_args(mrb, "o", &obj);
305
306 if (mrb_stat(mrb, obj, &st) < 0)
307 return mrb_false_value();
308 if (st.st_size == 0)
309 return mrb_true_value();
310
311 return mrb_false_value();
312}
313
314/*
315 * call-seq:
316 * File.size(file_name) -> integer
317 *
318 * Returns the size of <code>file_name</code>.
319 *
320 * _file_name_ can be an IO object.
321 */
322
323mrb_value
324mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
325{
326 struct stat st;
327 mrb_value obj;
328
329 mrb_get_args(mrb, "o", &obj);
330
331 if (mrb_stat(mrb, obj, &st) < 0)
332 mrb_sys_fail(mrb, "mrb_stat");
333
334 return mrb_fixnum_value(st.st_size);
335}
336
337/*
338 * call-seq:
339 * File.size?(file_name) -> Integer or nil
340 *
341 * Returns +nil+ if +file_name+ doesn't exist or has zero size, the size of the
342 * file otherwise.
343 */
344
345mrb_value
346mrb_filetest_s_size_p(mrb_state *mrb, mrb_value klass)
347{
348 struct stat st;
349 mrb_value obj;
350
351 mrb_get_args(mrb, "o", &obj);
352
353 if (mrb_stat(mrb, obj, &st) < 0)
354 return mrb_nil_value();
355 if (st.st_size == 0)
356 return mrb_nil_value();
357
358 return mrb_fixnum_value(st.st_size);
359}
360
361void
362mrb_init_file_test(mrb_state *mrb)
363{
364 struct RClass *f;
365
366 f = mrb_define_class(mrb, "FileTest", mrb->object_class);
367
368 mrb_define_class_method(mrb, f, "directory?", mrb_filetest_s_directory_p, MRB_ARGS_REQ(1));
369 mrb_define_class_method(mrb, f, "exist?", mrb_filetest_s_exist_p, MRB_ARGS_REQ(1));
370 mrb_define_class_method(mrb, f, "exists?", mrb_filetest_s_exist_p, MRB_ARGS_REQ(1));
371 mrb_define_class_method(mrb, f, "file?", mrb_filetest_s_file_p, MRB_ARGS_REQ(1));
372 mrb_define_class_method(mrb, f, "pipe?", mrb_filetest_s_pipe_p, MRB_ARGS_REQ(1));
373 mrb_define_class_method(mrb, f, "size", mrb_filetest_s_size, MRB_ARGS_REQ(1));
374 mrb_define_class_method(mrb, f, "size?", mrb_filetest_s_size_p, MRB_ARGS_REQ(1));
375 mrb_define_class_method(mrb, f, "socket?", mrb_filetest_s_socket_p, MRB_ARGS_REQ(1));
376 mrb_define_class_method(mrb, f, "symlink?", mrb_filetest_s_symlink_p, MRB_ARGS_REQ(1));
377 mrb_define_class_method(mrb, f, "zero?", mrb_filetest_s_zero_p, MRB_ARGS_REQ(1));
378}
Note: See TracBrowser for help on using the repository browser.