source: EcnlProtoTool/trunk/mrbgems/mruby-dir/src/dir.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.0 KB
Line 
1/*
2** dir.c - Dir
3**
4** See Copyright Notice in mruby.h
5*/
6
7#include "mruby.h"
8#include "mruby/class.h"
9#include "mruby/data.h"
10#include "mruby/string.h"
11#include "error.h"
12#include <sys/types.h>
13#if (defined(_WIN32) || defined(_WIN64)) && !defined(MUSL_LIBC)
14 #define MAXPATHLEN 1024
15 #if !defined(PATH_MAX)
16 #define PATH_MAX MAX_PATH
17 #endif
18 #define S_ISDIR(B) ((B)&_S_IFDIR)
19 #include "Win/dirent.c"
20 #include <direct.h>
21 #define rmdir _rmdir
22 #define getcwd _getcwd
23 #define mkdir _mkdir
24 #define chdir _chdir
25#elif defined(__NEWLIB__)
26 #include <sys/param.h>
27 #include "_dirent.h"
28 #include <unistd.h>
29#else
30 #include <sys/param.h>
31 #include <dirent.h>
32 #include <unistd.h>
33#endif
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <signal.h>
39#include <string.h>
40
41/* with/without IO module */
42#ifdef ENABLE_IO
43#include "mruby/ext/io.h"
44#else
45#define E_IO_ERROR E_RUNTIME_ERROR
46#endif
47
48struct mrb_dir {
49 DIR *dir;
50};
51
52void
53mrb_dir_free(mrb_state *mrb, void *ptr)
54{
55 struct mrb_dir *mdir = (struct mrb_dir *)ptr;
56
57 if (mdir->dir) {
58 closedir(mdir->dir);
59 mdir->dir = NULL;
60 }
61 mrb_free(mrb, mdir);
62}
63
64static struct mrb_data_type mrb_dir_type = { "DIR", mrb_dir_free };
65
66mrb_value
67mrb_dir_close(mrb_state *mrb, mrb_value self)
68{
69 struct mrb_dir *mdir;
70 mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
71 if (!mdir) return mrb_nil_value();
72 if (!mdir->dir) {
73 mrb_raise(mrb, E_IO_ERROR, "closed directory");
74 }
75 if (closedir(mdir->dir) == -1) {
76 mrb_sys_fail(mrb, "closedir");
77 }
78 mdir->dir = NULL;
79 return mrb_nil_value();
80}
81
82mrb_value
83mrb_dir_init(mrb_state *mrb, mrb_value self)
84{
85 DIR *dir;
86 struct mrb_dir *mdir;
87 mrb_value path;
88 char *cpath;
89
90 mdir = (struct mrb_dir *)DATA_PTR(self);
91 if (mdir) {
92 mrb_dir_free(mrb, mdir);
93 }
94 DATA_TYPE(self) = &mrb_dir_type;
95 DATA_PTR(self) = NULL;
96
97 mdir = (struct mrb_dir *)mrb_malloc(mrb, sizeof(*mdir));
98 mdir->dir = NULL;
99 DATA_PTR(self) = mdir;
100
101 mrb_get_args(mrb, "S", &path);
102 cpath = mrb_str_to_cstr(mrb, path);
103 if ((dir = opendir(cpath)) == NULL) {
104 mrb_sys_fail(mrb, cpath);
105 }
106 mdir->dir = dir;
107 return self;
108}
109
110mrb_value
111mrb_dir_delete(mrb_state *mrb, mrb_value klass)
112{
113 mrb_value path;
114 char *cpath;
115
116 mrb_get_args(mrb, "S", &path);
117 cpath = mrb_str_to_cstr(mrb, path);
118 if (rmdir(cpath) == -1) {
119 mrb_sys_fail(mrb, cpath);
120 }
121 return mrb_fixnum_value(0);
122}
123
124mrb_value
125mrb_dir_existp(mrb_state *mrb, mrb_value klass)
126{
127 mrb_value path;
128 struct stat sb;
129 char *cpath;
130
131 mrb_get_args(mrb, "S", &path);
132 cpath = mrb_str_to_cstr(mrb, path);
133 if (stat(cpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
134 return mrb_true_value();
135 } else {
136 return mrb_false_value();
137 }
138}
139
140mrb_value
141mrb_dir_getwd(mrb_state *mrb, mrb_value klass)
142{
143 mrb_value path;
144
145 path = mrb_str_buf_new(mrb, MAXPATHLEN);
146 if (getcwd(RSTRING_PTR(path), MAXPATHLEN) == NULL) {
147 mrb_sys_fail(mrb, "getcwd(2)");
148 }
149 mrb_str_resize(mrb, path, strlen(RSTRING_PTR(path)));
150 return path;
151}
152
153mrb_value
154mrb_dir_mkdir(mrb_state *mrb, mrb_value klass)
155{
156 mrb_int mode;
157 mrb_value spath;
158 char *path;
159
160 mode = 0777;
161 mrb_get_args(mrb, "S|i", &spath, &mode);
162 path = mrb_str_to_cstr(mrb, spath);
163#if (!defined(_WIN32) && !defined(_WIN64)) || defined(MUSL_LIBC)
164 if (mkdir(path, mode) == -1) {
165#else
166 if (mkdir(path) == -1) {
167#endif
168 mrb_sys_fail(mrb, path);
169 }
170 return mrb_fixnum_value(0);
171}
172
173mrb_value
174mrb_dir_chdir(mrb_state *mrb, mrb_value klass)
175{
176 mrb_value spath;
177 char *path;
178
179 mrb_get_args(mrb, "S", &spath);
180 path = mrb_str_to_cstr(mrb, spath);
181 if (chdir(path) == -1) {
182 mrb_sys_fail(mrb, path);
183 }
184 return mrb_fixnum_value(0);
185}
186
187mrb_value
188mrb_dir_chroot(mrb_state *mrb, mrb_value self)
189{
190 #if defined(_WIN32) || defined(_WIN64) || defined(__android__)
191 mrb_raise(mrb, E_NOTIMP_ERROR, "chroot() unreliable on Win platforms");
192 return mrb_fixnum_value(0);
193 #else
194 mrb_value spath;
195 char *path;
196 int res;
197
198 mrb_get_args(mrb, "S", &spath);
199 path = mrb_str_to_cstr(mrb, spath);
200 res = chroot(path);
201 if (res == -1) {
202 mrb_sys_fail(mrb, path);
203 }
204
205 return mrb_fixnum_value(res);
206 #endif
207}
208
209mrb_value
210mrb_dir_read(mrb_state *mrb, mrb_value self)
211{
212 struct mrb_dir *mdir;
213 struct dirent *dp;
214
215 mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
216 if (!mdir) return mrb_nil_value();
217 if (!mdir->dir) {
218 mrb_raise(mrb, E_IO_ERROR, "closed directory");
219 }
220 dp = readdir(mdir->dir);
221 if (dp != NULL) {
222 return mrb_str_new_cstr(mrb, dp->d_name);
223 } else {
224 return mrb_nil_value();
225 }
226}
227
228mrb_value
229mrb_dir_rewind(mrb_state *mrb, mrb_value self)
230{
231 struct mrb_dir *mdir;
232
233 mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
234 if (!mdir) return mrb_nil_value();
235 if (!mdir->dir) {
236 mrb_raise(mrb, E_IO_ERROR, "closed directory");
237 }
238 rewinddir(mdir->dir);
239 return self;
240}
241
242mrb_value
243mrb_dir_seek(mrb_state *mrb, mrb_value self)
244{
245 #if defined(_WIN32) || defined(_WIN64) || defined(__android__)
246 mrb_raise(mrb, E_NOTIMP_ERROR, "dirseek() unreliable on Win platforms");
247 return self;
248 #else
249 struct mrb_dir *mdir;
250 mrb_int pos;
251
252 mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
253 if (!mdir) return mrb_nil_value();
254 if (!mdir->dir) {
255 mrb_raise(mrb, E_IO_ERROR, "closed directory");
256 }
257 mrb_get_args(mrb, "i", &pos);
258 seekdir(mdir->dir, (long)pos);
259 return self;
260 #endif
261}
262
263mrb_value
264mrb_dir_tell(mrb_state *mrb, mrb_value self)
265{
266 #if defined(_WIN32) || defined(_WIN64) || defined(__android__)
267 mrb_raise(mrb, E_NOTIMP_ERROR, "dirtell() unreliable on Win platforms");
268 return mrb_fixnum_value(0);
269 #else
270 struct mrb_dir *mdir;
271 mrb_int pos;
272
273 mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
274 if (!mdir) return mrb_nil_value();
275 if (!mdir->dir) {
276 mrb_raise(mrb, E_IO_ERROR, "closed directory");
277 }
278 pos = (mrb_int)telldir(mdir->dir);
279 return mrb_fixnum_value(pos);
280 #endif
281}
282
283void
284mrb_mruby_dir_gem_init(mrb_state *mrb)
285{
286 struct RClass *d;
287
288 d = mrb_define_class(mrb, "Dir", mrb->object_class);
289 MRB_SET_INSTANCE_TT(d, MRB_TT_DATA);
290 mrb_define_class_method(mrb, d, "delete", mrb_dir_delete, MRB_ARGS_REQ(1));
291 mrb_define_class_method(mrb, d, "exist?", mrb_dir_existp, MRB_ARGS_REQ(1));
292 mrb_define_class_method(mrb, d, "getwd", mrb_dir_getwd, MRB_ARGS_NONE());
293 mrb_define_class_method(mrb, d, "mkdir", mrb_dir_mkdir, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
294 mrb_define_class_method(mrb, d, "_chdir", mrb_dir_chdir, MRB_ARGS_REQ(1));
295 mrb_define_class_method(mrb, d, "chroot", mrb_dir_chroot, MRB_ARGS_REQ(1));
296
297 mrb_define_method(mrb, d, "close", mrb_dir_close, MRB_ARGS_NONE());
298 mrb_define_method(mrb, d, "initialize", mrb_dir_init, MRB_ARGS_REQ(1));
299 mrb_define_method(mrb, d, "read", mrb_dir_read, MRB_ARGS_NONE());
300 mrb_define_method(mrb, d, "rewind", mrb_dir_rewind, MRB_ARGS_NONE());
301 mrb_define_method(mrb, d, "seek", mrb_dir_seek, MRB_ARGS_REQ(1));
302 mrb_define_method(mrb, d, "tell", mrb_dir_tell, MRB_ARGS_NONE());
303}
304
305void
306mrb_mruby_dir_gem_final(mrb_state *mrb)
307{
308}
Note: See TracBrowser for help on using the repository browser.