1 /***********************************************************/
2 /*                                                         */
3 /*  File system stuff                                      */
4 /*                                                         */
5 /***********************************************************/
6 
7 #include <apricot.h>
8 #include <sys/stat.h>
9 #include "unix/guts.h"
10 #include "Application.h"
11 #include "File.h"
12 
13 void
prima_rebuild_watchers(void)14 prima_rebuild_watchers( void)
15 {
16 	int i;
17 	PFile f;
18 
19 	FD_ZERO( &guts.read_set);
20 	FD_ZERO( &guts.write_set);
21 	FD_ZERO( &guts.excpt_set);
22 	FD_SET( guts.connection, &guts.read_set);
23 	guts.max_fd = guts.connection;
24 	for ( i = 0; i < guts.files->count; i++) {
25 		f = (PFile)list_at( guts.files,i);
26 		if ( f-> eventMask & feRead) {
27 			FD_SET( f->fd, &guts.read_set);
28 			if ( f->fd > guts.max_fd)
29 				guts.max_fd = f->fd;
30 		}
31 		if ( f-> eventMask & feWrite) {
32 			FD_SET( f->fd, &guts.write_set);
33 			if ( f->fd > guts.max_fd)
34 				guts.max_fd = f->fd;
35 		}
36 		if ( f-> eventMask & feException) {
37 			FD_SET( f->fd, &guts.excpt_set);
38 			if ( f->fd > guts.max_fd)
39 				guts.max_fd = f->fd;
40 		}
41 	}
42 }
43 
44 Bool
apc_file_attach(Handle self)45 apc_file_attach( Handle self)
46 {
47 	if ( PFile(self)->fd >= FD_SETSIZE ) return false;
48 
49 	if ( list_index_of( guts.files, self) >= 0) {
50 		prima_rebuild_watchers();
51 		return true;
52 	}
53 	protect_object( self);
54 	list_add( guts.files, self);
55 	prima_rebuild_watchers();
56 	return true;
57 }
58 
59 Bool
apc_file_detach(Handle self)60 apc_file_detach( Handle self)
61 {
62 	int i;
63 	if (( i = list_index_of( guts.files, self)) >= 0) {
64 		list_delete_at( guts.files, i);
65 		unprotect_object( self);
66 		prima_rebuild_watchers();
67 	}
68 	return true;
69 }
70 
71 Bool
apc_file_change_mask(Handle self)72 apc_file_change_mask( Handle self)
73 {
74 	return apc_file_attach( self);
75 }
76 
77 PList
apc_getdir(const char * dirname,Bool is_utf8)78 apc_getdir( const char *dirname, Bool is_utf8)
79 {
80 	DIR *dh;
81 	struct dirent *de;
82 	PList dirlist = NULL;
83 	char *type;
84 	char path[ 2048];
85 	struct stat s;
86 
87 	if (( dh = opendir( dirname)) && (dirlist = plist_create( 50, 50))) {
88 		while (( de = readdir( dh))) {
89 			list_add( dirlist, (Handle)duplicate_string( de-> d_name));
90 #if defined(DT_REG) && defined(DT_DIR)
91 			switch ( de-> d_type) {
92 			case DT_FIFO:	type = "fifo";	break;
93 			case DT_CHR:	type = "chr";	break;
94 			case DT_DIR:	type = "dir";	break;
95 			case DT_BLK:	type = "blk";	break;
96 			case DT_REG:	type = "reg";	break;
97 			case DT_LNK:	type = "lnk";	break;
98 			case DT_SOCK:	type = "sock";	break;
99 #ifdef DT_WHT
100 			case DT_WHT:	type = "wht";	break;
101 #endif
102 			default:
103 #endif
104 				snprintf( path, 2047, "%s/%s", dirname, de-> d_name);
105 				type = NULL;
106 				if ( stat( path, &s) == 0) {
107 					switch ( s. st_mode & S_IFMT) {
108 					case S_IFIFO:        type = "fifo";  break;
109 					case S_IFCHR:        type = "chr";   break;
110 					case S_IFDIR:        type = "dir";   break;
111 					case S_IFBLK:        type = "blk";   break;
112 					case S_IFREG:        type = "reg";   break;
113 					case S_IFLNK:        type = "lnk";   break;
114 					case S_IFSOCK:       type = "sock";  break;
115 #ifdef S_IFWHT
116 					case S_IFWHT:        type = "wht";   break;
117 #endif
118 					}
119 				}
120 				if ( !type)     type = "unknown";
121 #if defined(DT_REG) && defined(DT_DIR)
122 			}
123 #endif
124 			list_add( dirlist, (Handle)duplicate_string( type));
125 		}
126 		closedir( dh);
127 	}
128 	return dirlist;
129 }
130 
131 int
apc_fs_access(const char * name,Bool is_utf8,int mode,Bool effective)132 apc_fs_access(const char *name, Bool is_utf8, int mode, Bool effective)
133 {
134 	return
135 #ifdef HAVE_EACCESS
136 		effective ?  eaccess(name, mode) :
137 #endif
138 		access(name, mode);
139 }
140 
141 Bool
apc_fs_chdir(const char * path,Bool is_utf8)142 apc_fs_chdir(const char *path, Bool is_utf8 )
143 {
144 	return chdir(path) == 0;
145 }
146 
147 Bool
apc_fs_chmod(const char * path,Bool is_utf8,int mode)148 apc_fs_chmod( const char *path, Bool is_utf8, int mode)
149 {
150 	return chmod(path, mode) == 0;
151 }
152 
153 Bool
apc_fs_closedir(PDirHandleRec dh)154 apc_fs_closedir( PDirHandleRec dh)
155 {
156 	return closedir(dh->handle) == 0;
157 }
158 
159 char *
apc_fs_from_local(const char * text,int * len)160 apc_fs_from_local(const char * text, int * len)
161 {
162 	return (char*) text;
163 }
164 
165 char*
apc_fs_getcwd()166 apc_fs_getcwd()
167 {
168 	char pwd[PATH_MAX];
169 	return getcwd(pwd, sizeof(pwd)) == NULL ? NULL : duplicate_string(pwd);
170 }
171 
172 char *
apc_fs_to_local(const char * text,Bool fail_if_cannot,int * len)173 apc_fs_to_local(const char * text, Bool fail_if_cannot, int * len)
174 {
175 	return (char*)text;
176 }
177 
178 char*
apc_fs_getenv(const char * varname,Bool is_utf8,Bool * do_free)179 apc_fs_getenv(const char * varname, Bool is_utf8, Bool * do_free)
180 {
181 	*do_free = false;
182 	return getenv(varname);
183 }
184 
185 Bool
apc_fs_link(const char * oldname,Bool is_old_utf8,const char * newname,Bool is_new_utf8)186 apc_fs_link( const char* oldname, Bool is_old_utf8, const char * newname, Bool is_new_utf8 )
187 {
188 	return link(oldname, newname) == 0;
189 }
190 
191 Bool
apc_fs_mkdir(const char * path,Bool is_utf8,int mode)192 apc_fs_mkdir( const char* path, Bool is_utf8, int mode)
193 {
194 	return mkdir(path, mode) == 0;
195 }
196 
197 Bool
apc_fs_opendir(const char * path,PDirHandleRec dh)198 apc_fs_opendir( const char* path, PDirHandleRec dh)
199 {
200 	return (dh->handle = opendir(path)) != NULL;
201 }
202 
203 int
apc_fs_open_file(const char * path,Bool is_utf8,int flags,int mode)204 apc_fs_open_file( const char* path, Bool is_utf8, int flags, int mode)
205 {
206 	return open(path, flags, mode);
207 }
208 
209 Bool
apc_fs_readdir(PDirHandleRec dh,char * entry)210 apc_fs_readdir( PDirHandleRec dh, char * entry)
211 {
212 	struct dirent *de;
213 	if ( !( de = readdir(dh->handle)))
214 		return false;
215 	strncpy( entry, de->d_name, PATH_MAX_UTF8);
216 	return true;
217 }
218 
219 Bool
apc_fs_rename(const char * oldname,Bool is_old_utf8,const char * newname,Bool is_new_utf8)220 apc_fs_rename( const char* oldname, Bool is_old_utf8, const char * newname, Bool is_new_utf8 )
221 {
222 	return rename(oldname, newname) == 0;
223 }
224 
225 Bool
apc_fs_rewinddir(PDirHandleRec dh)226 apc_fs_rewinddir( PDirHandleRec dh )
227 {
228 	rewinddir(dh->handle);
229 	return true;
230 }
231 
232 Bool
apc_fs_rmdir(const char * path,Bool is_utf8)233 apc_fs_rmdir( const char* path, Bool is_utf8 )
234 {
235 	return rmdir(path) == 0;
236 }
237 
238 Bool
apc_fs_seekdir(PDirHandleRec dh,long position)239 apc_fs_seekdir( PDirHandleRec dh, long position )
240 {
241 	seekdir(dh->handle, position);
242 	return true;
243 }
244 
245 Bool
apc_fs_setenv(const char * varname,Bool is_name_utf8,const char * value,Bool is_value_utf8)246 apc_fs_setenv(const char * varname, Bool is_name_utf8, const char * value, Bool is_value_utf8)
247 {
248 	Perl_my_setenv(aTHX_ varname, value);
249 	return true;
250 }
251 
252 Bool
apc_fs_stat(const char * name,Bool is_utf8,Bool link,PStatRec statrec)253 apc_fs_stat(const char *name, Bool is_utf8, Bool link, PStatRec statrec)
254 {
255 	struct stat statbuf;
256 	if ( link ) {
257 		if ( lstat(name, &statbuf) < 0 )
258 			return 0;
259 	} else {
260 		if ( stat(name, &statbuf) < 0 )
261 			return 0;
262 	}
263 	statrec-> dev     = statbuf. st_dev;
264 	statrec-> ino     = statbuf. st_ino;
265 	statrec-> mode    = statbuf. st_mode;
266 	statrec-> nlink   = statbuf. st_nlink;
267 	statrec-> uid     = statbuf. st_uid;
268 	statrec-> gid     = statbuf. st_gid;
269 	statrec-> rdev    = statbuf. st_rdev;
270 	statrec-> size    = statbuf. st_size;
271 	statrec-> blksize = statbuf. st_blksize;
272 	statrec-> blocks  = statbuf. st_blocks;
273 #ifdef __APPLE__
274 #define ST_F(a) st_##a##timespec
275 #else
276 #define ST_F(a) st_##a##tim
277 #endif
278 	statrec-> atim    = (float) statbuf.ST_F(a).tv_sec + (float) statbuf.ST_F(a).tv_nsec / 1000000000.0;
279 	statrec-> mtim    = (float) statbuf.ST_F(m).tv_sec + (float) statbuf.ST_F(m).tv_nsec / 1000000000.0;
280 	statrec-> ctim    = (float) statbuf.ST_F(c).tv_sec + (float) statbuf.ST_F(c).tv_nsec / 1000000000.0;
281 #undef ST_F
282 	return 1;
283 }
284 
285 long
apc_fs_telldir(PDirHandleRec dh)286 apc_fs_telldir( PDirHandleRec dh )
287 {
288 	return telldir(dh-> handle);
289 }
290 
291 Bool
apc_fs_unlink(const char * path,Bool is_utf8)292 apc_fs_unlink( const char* path, Bool is_utf8 )
293 {
294 	return unlink(path) == 0;
295 }
296 
297 Bool
apc_fs_utime(double atime,double mtime,const char * path,Bool is_utf8)298 apc_fs_utime( double atime, double mtime, const char* path, Bool is_utf8 )
299 {
300 	struct timeval tv[2];
301 	tv[0].tv_sec  = (long) atime;
302 	tv[0].tv_usec = (atime - (float) tv[0].tv_sec) * 1000000;
303 	tv[1].tv_sec  = (long) mtime;
304 	tv[1].tv_usec = (mtime - (float) tv[1].tv_sec) * 1000000;
305 
306 	return utimes(path, tv) == 0;
307 }
308 
309