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

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

mrubyを2.1.1に更新

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