1 #include "apricot.h"
2 #include "Utils.h"
3 #include <Utils.inc>
4
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8
9
Utils_query_drives_map(char * firstDrive)10 SV *Utils_query_drives_map( char *firstDrive)
11 {
12 char map[ 256];
13 apc_query_drives_map( firstDrive, map, sizeof( map));
14 return newSVpv( map, 0);
15 }
16
17 int
Utils_get_os(void)18 Utils_get_os(void)
19 {
20 return apc_application_get_os_info( NULL, 0, NULL, 0, NULL, 0, NULL, 0);
21 }
22
23 int
Utils_get_gui(void)24 Utils_get_gui(void)
25 {
26 return apc_application_get_gui_info( NULL, 0, NULL, 0);
27 }
28
Utils_ceil(double x)29 long Utils_ceil( double x)
30 {
31 return ceil( x);
32 }
33
Utils_floor(double x)34 long Utils_floor( double x)
35 {
36 return floor( x);
37 }
38
39 static Bool
is_valid_utf8(unsigned char * str)40 is_valid_utf8( unsigned char * str )
41 {
42 int len = 0, hi8 = 0;
43 unsigned char * c = str;
44 while (*c) {
45 len++;
46 if ( *c > 0x7f ) hi8 = 1;
47 c++;
48 }
49 if ( !hi8 ) return false;
50 #if PERL_PATCHLEVEL >= 22
51 while ( str < c ) {
52 unsigned char * end = utf8_hop( str, 1 );
53 if ( end > c ) return false;
54 if ( !isUTF8_CHAR(str, end))
55 return false;
56 str = end;
57 }
58 #endif
59 return true;
60 }
61
XS(Utils_getdir_FROMPERL)62 XS(Utils_getdir_FROMPERL) {
63 dXSARGS;
64 Bool wantarray = ( GIMME_V == G_ARRAY);
65 char *dirname;
66 PList dirlist;
67 int i;
68
69 if ( items >= 2) {
70 croak( "invalid usage of Prima::Utils::getdir");
71 }
72 dirname = SvPV_nolen( ST( 0));
73 dirlist = apc_getdir( dirname, prima_is_utf8_sv(ST(0)));
74 SPAGAIN;
75 SP -= items;
76 if ( wantarray) {
77 if ( dirlist) {
78 EXTEND( sp, dirlist-> count);
79 for ( i = 0; i < dirlist-> count; i++) {
80 char * entry = ( char *)dirlist-> items[i];
81 SV * sv = newSVpv(entry, 0);
82 if (is_valid_utf8((unsigned char*) entry))
83 SvUTF8_on(sv);
84 PUSHs( sv_2mortal(sv));
85 free(( char *)dirlist-> items[i]);
86 }
87 plist_destroy( dirlist);
88 }
89 } else {
90 if ( dirlist) {
91 XPUSHs( sv_2mortal( newSViv( dirlist-> count / 2)));
92 for ( i = 0; i < dirlist-> count; i++) {
93 free(( char *)dirlist-> items[i]);
94 }
95 plist_destroy( dirlist);
96 } else {
97 XPUSHs( &PL_sv_undef);
98 }
99 }
100 PUTBACK;
101 return;
102 }
103
104 int
Utils_access(SV * path,int mode,Bool effective)105 Utils_access( SV* path, int mode, Bool effective )
106 {
107 return apc_fs_access( SvPV_nolen(path), prima_is_utf8_sv(path), mode, effective);
108 }
109
110 Bool
Utils_chdir(SV * path)111 Utils_chdir( SV* path )
112 {
113 return apc_fs_chdir( SvPV_nolen(path), prima_is_utf8_sv(path));
114 }
115
116 Bool
Utils_chmod(SV * path,int mode)117 Utils_chmod( SV* path, int mode)
118 {
119 return apc_fs_chmod( SvPV_nolen(path), prima_is_utf8_sv(path), mode);
120 }
121
122 static PDirHandleRec
get_dh(const char * method,SV * sv)123 get_dh(const char * method, SV * sv)
124 {
125 PDirHandleRec d;
126 if ( !SvROK(sv) || SvTYPE( SvRV( sv)) != SVt_PVMG)
127 goto WARN;
128 if ( !sv_isa( sv, "Prima::Utils::DIRHANDLE" ))
129 goto WARN;
130 d = (PDirHandleRec) prima_array_get_storage(SvRV(sv));
131 if (!d-> is_active) {
132 errno = EBADF;
133 return false;
134 }
135 return d;
136
137 WARN:
138 warn("Prima::Utils::%s: invalid dirhandle", method);
139 errno = EBADF;
140 return false;
141 }
142
143 Bool
Utils_closedir(SV * dh)144 Utils_closedir(SV * dh)
145 {
146 PDirHandleRec d;
147 if (( d = get_dh("closedir", dh)) == NULL )
148 return false;
149 d-> is_active = false;
150 return apc_fs_closedir(d);
151 }
152
153 SV*
Utils_getcwd()154 Utils_getcwd()
155 {
156 SV * ret;
157 char *cwd;
158
159 if (( cwd = apc_fs_getcwd()) == NULL )
160 return NULL_SV;
161 ret = newSVpv( cwd, 0 );
162 if ( is_valid_utf8((unsigned char*) cwd))
163 SvUTF8_on(ret);
164 free(cwd);
165 return ret;
166 }
167
168 SV*
Utils_getenv(SV * varname)169 Utils_getenv(SV * varname)
170 {
171 SV * ret;
172 char *val;
173 Bool is_utf8, do_free = false;
174
175 is_utf8 = prima_is_utf8_sv(varname);
176 if (( val = apc_fs_getenv(SvPV_nolen(varname), is_utf8, &do_free)) == NULL )
177 return NULL_SV;
178 ret = newSVpv( val, 0 );
179 if ( is_valid_utf8((unsigned char*) val))
180 SvUTF8_on(ret);
181 if ( do_free ) free(val);
182 return ret;
183 }
184
185 SV *
Utils_last_error()186 Utils_last_error()
187 {
188 SV * ret = NULL_SV;
189 char * p = apc_last_error();
190 if ( p ) {
191 ret = newSVpv( p, 0);
192 free(p);
193 }
194 return ret;
195 }
196
197 Bool
Utils_link(SV * oldname,SV * newname)198 Utils_link( SV* oldname, SV * newname )
199 {
200 return apc_fs_link(
201 SvPV_nolen(oldname), prima_is_utf8_sv(oldname),
202 SvPV_nolen(newname), prima_is_utf8_sv(newname)
203 );
204 }
205
206 SV *
Utils_local2sv(SV * text)207 Utils_local2sv(SV * text)
208 {
209 SV * ret;
210 char * buf, *src;
211 STRLEN xlen;
212 int len;
213 if ( prima_is_utf8_sv(text) )
214 return newSVsv( text );
215 src = SvPV(text, xlen);
216 len = xlen;
217 if ( !( buf = apc_fs_from_local(src, &len)))
218 return NULL_SV;
219 if ( buf == src ) {
220 ret = newSVsv( text );
221 if ( is_valid_utf8((unsigned char*) src))
222 SvUTF8_on(ret);
223 return ret;
224 }
225
226 ret = newSVpv( buf, len );
227 if ( is_valid_utf8((unsigned char*) buf))
228 SvUTF8_on(ret);
229 free(buf);
230
231 return ret;
232 }
233
234
235 Bool
Utils_mkdir(SV * path,int mode)236 Utils_mkdir( SV* path, int mode)
237 {
238 return apc_fs_mkdir( SvPV_nolen(path), prima_is_utf8_sv(path), mode);
239 }
240
241 SV *
Utils_open_dir(SV * path)242 Utils_open_dir(SV * path)
243 {
244 SV * ret = NULL_SV;
245 PDirHandleRec dh;
246 SV * dhsv;
247
248 if (( dhsv = prima_array_new(sizeof(DirHandleRec))) == NULL) {
249 errno = ENOMEM;
250 return NULL_SV;
251 }
252 if (( dh = (PDirHandleRec) prima_array_get_storage(dhsv)) == NULL) {
253 errno = ENOMEM;
254 return NULL_SV;
255 }
256 bzero(dh, sizeof(DirHandleRec));
257 dh-> is_utf8 = prima_is_utf8_sv(path);
258 if ( !apc_fs_opendir( SvPV_nolen(path), dh)) {
259 sv_free(dhsv);
260 return NULL_SV;
261 }
262 dh-> is_active = true;
263
264 ret = newRV_noinc(dhsv);
265 sv_bless(ret, gv_stashpv("Prima::Utils::DIRHANDLE", GV_ADD));
266
267
268 return ret;
269 }
270
271 int
Utils_open_file(SV * path,int mode,int perms)272 Utils_open_file( SV* path, int mode, int perms)
273 {
274 return apc_fs_open_file( SvPV_nolen(path), prima_is_utf8_sv(path), mode, perms);
275 }
276
277 SV*
Utils_read_dir(SV * dh)278 Utils_read_dir(SV * dh)
279 {
280 PDirHandleRec d;
281 char buf[PATH_MAX_UTF8];
282 SV * ret;
283 if (( d = get_dh("read_dir", dh)) == NULL ) {
284 errno = EBADF;
285 warn("Prima::Utils::read_dir: invalid dirhandle");
286 return NULL_SV;
287 }
288 if (!d-> is_active) {
289 errno = EBADF;
290 return NULL_SV;
291 }
292
293 if ( !apc_fs_readdir(d, buf)) return NULL_SV;
294
295 ret = newSVpv(buf, 0);
296 if (is_valid_utf8((unsigned char*) buf))
297 SvUTF8_on(ret);
298
299 return ret;
300 }
301
302 Bool
Utils_rename(SV * oldpath,SV * newpath)303 Utils_rename( SV* oldpath, SV * newpath )
304 {
305 return apc_fs_rename(
306 SvPV_nolen(oldpath), prima_is_utf8_sv(oldpath),
307 SvPV_nolen(newpath), prima_is_utf8_sv(newpath)
308 );
309 }
310
311 Bool
Utils_rewinddir(SV * dh)312 Utils_rewinddir( SV * dh )
313 {
314 PDirHandleRec d;
315 if (( d = get_dh("rewinddir", dh)) == NULL )
316 return false;
317 return apc_fs_rewinddir(d);
318 }
319
320 Bool
Utils_rmdir(SV * path)321 Utils_rmdir( SV* path )
322 {
323 return apc_fs_rmdir( SvPV_nolen(path), prima_is_utf8_sv(path));
324 }
325
326 Bool
Utils_seekdir(SV * dh,long position)327 Utils_seekdir( SV * dh, long position )
328 {
329 PDirHandleRec d;
330 if (( d = get_dh("seekdir", dh)) == NULL )
331 return false;
332 return apc_fs_seekdir(d, position);
333 }
334
335 Bool
Utils_setenv(SV * varname,SV * value)336 Utils_setenv(SV * varname, SV * value)
337 {
338 return apc_fs_setenv(
339 SvPV_nolen(varname), prima_is_utf8_sv(varname),
340 (SvTYPE(value) != SVt_NULL) ? SvPV_nolen(value) : NULL,
341 (SvTYPE(value) != SVt_NULL) ? prima_is_utf8_sv(value) : false
342 );
343 }
344
XS(Utils_stat_FROMPERL)345 XS(Utils_stat_FROMPERL) {
346 dXSARGS;
347 char *name;
348 StatRec stats;
349 int ok;
350 Bool link = false;
351 U8 gimme;
352
353 if ( items > 2)
354 croak( "invalid usage of Prima::Utils::stat");
355 if ( items > 1 )
356 link = SvBOOL(ST(1));
357
358 name = SvPV_nolen( ST( 0));
359 ok = apc_fs_stat( name, prima_is_utf8_sv(ST(0)), link, &stats);
360 SPAGAIN;
361 SP -= items;
362 gimme = GIMME_V;
363 if ( gimme != G_ARRAY ) {
364 if ( gimme != G_VOID )
365 XPUSHs(newSViv(ok));
366 } else if ( ok) {
367 EXTEND( sp, 11 );
368 PUSHs( sv_2mortal(newSVuv( stats. dev )));
369 PUSHs( sv_2mortal(newSVuv( stats. ino )));
370 PUSHs( sv_2mortal(newSVuv( stats. mode )));
371 PUSHs( sv_2mortal(newSVuv( stats. nlink )));
372 PUSHs( sv_2mortal(newSVuv( stats. uid )));
373 PUSHs( sv_2mortal(newSVuv( stats. gid )));
374 PUSHs( sv_2mortal(newSVuv( stats. rdev )));
375 PUSHs( sv_2mortal(newSVuv( stats. size )));
376 PUSHs( sv_2mortal(newSVnv( stats. atim )));
377 PUSHs( sv_2mortal(newSVnv( stats. mtim )));
378 PUSHs( sv_2mortal(newSVnv( stats. ctim )));
379 if (stats. blksize >= 0 )
380 XPUSHs( sv_2mortal(newSVuv( stats. blksize)));
381 if (stats. blocks >= 0 )
382 XPUSHs( sv_2mortal(newSVuv( stats. blocks )));
383 }
384 PUTBACK;
385 return;
386 }
387
388 static int
utf8len(const char * utf8,int maxlen)389 utf8len( const char * utf8, int maxlen)
390 {
391 int ulen = 0;
392 while ( maxlen > 0 ) {
393 const char *u = (char*) utf8_hop(( U8*) utf8, 1);
394 ulen++;
395 maxlen -= u - utf8;
396 utf8 = u;
397 }
398 return ulen;
399 }
400
401 long
Utils_telldir(SV * dh)402 Utils_telldir( SV * dh )
403 {
404 PDirHandleRec d;
405 if (( d = get_dh("telldir", dh)) == NULL )
406 return false;
407 return apc_fs_telldir(d);
408 }
409
410 SV *
Utils_sv2local(SV * text,Bool fail_if_cannot)411 Utils_sv2local(SV * text, Bool fail_if_cannot)
412 {
413 SV * ret;
414 char * buf, * src;
415 STRLEN xlen;
416 int len;
417 if ( !prima_is_utf8_sv(text) )
418 return newSVsv( text );
419 src = SvPV(text, xlen);
420 len = utf8len( src, xlen );
421 if ( !( buf = apc_fs_to_local(src, fail_if_cannot, &len)))
422 return NULL_SV;
423 if ( buf == src ) {
424 ret = newSVsv( text );
425 SvUTF8_off(ret);
426 return ret;
427 }
428 ret = newSVpv( buf, len );
429 free(buf);
430
431 return ret;
432 }
433
434
435 Bool
Utils_unlink(SV * path)436 Utils_unlink( SV* path )
437 {
438 return apc_fs_unlink( SvPV_nolen(path), prima_is_utf8_sv(path));
439 }
440
441 Bool
Utils_utime(double atime,double mtime,SV * path)442 Utils_utime( double atime, double mtime, SV* path )
443 {
444 return apc_fs_utime( atime, mtime, SvPV_nolen(path), prima_is_utf8_sv(path));
445 }
446
447 #ifdef __cplusplus
448 }
449 #endif
450