1 #include <stdlib.h>
2 #include <ctype.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/stat.h>
6 
7 #include "bosmeta.h"
8 #include "dosdir.h"
9 
10 #if 0
11 #include "nfd.h"
12 #define TRACE(x) NFD(x)
13 #define DEBUG(x) NFD(x)
14 #else
15 #define TRACE(x)
16 #define DEBUG(x)
17 #endif
18 
19 
20 /* x:\dev\phys folder lists respectively */
21 LIST root;
22 
23 static LIST root_dev;
24 static LIST root_dev_phys;
25 
26 /* cookie release/dup */
27 static
28 void release_cookie( FCOOKIE *fc);
29 
30 static
release_folder(LIST * f)31 void release_folder( LIST *f) {
32 	LINKABLE *fc = listFirst(f);
33 	while (fc) {
34 		FCOOKIE *trash = (FCOOKIE*)fc;
35 		fc = listNext(fc);
36 		release_cookie( trash);
37 	}
38 }
39 
40 static
release_cookie(FCOOKIE * fc)41 void release_cookie( FCOOKIE *fc) {
42 	release_folder( fc->folder);
43 	free( fc->name);
44 	free( fc);
45 }
46 
47 static
dup_cookie(FCOOKIE * s)48 FCOOKIE *dup_cookie( FCOOKIE *s) {
49 	FCOOKIE *fc;
50 	fc = malloc(sizeof(FCOOKIE));
51 	fc->name = strdup(s->name);
52 	fc->attr = s->attr;
53 	fc->folder = s->folder;
54 	fc->bos_dev = s->bos_dev;
55 	fc->bos_info_flags = s->bos_info_flags;
56 	return fc;
57 }
58 
bosfs_initialize(void)59 long bosfs_initialize(void) {
60 	int i;
61 	metainit_t metainit={0,0,0,0};
62 	FCOOKIE *fc;
63 
64 	Metainit(&metainit);
65 	TRACE(("MetaDOS version=%s, drives=%x\n", metainit.version, metainit.drives_map));
66 	if (metainit.version == NULL) {
67 		DEBUG(("MetaDOS not installed\n"));
68 		return -1;
69 	}
70 
71 	if (metainit.drives_map == 0) {
72 		DEBUG(("No MetaDOS devices present\n"));
73 		return -1;
74 	}
75 
76 	listInit( &root);
77 
78 	{ /* create the x:\dev folder */
79 		fc = malloc(sizeof(FCOOKIE));
80 		fc->name = strdup("dev");
81 		fc->attr = FA_DIR;
82 		fc->folder = &root_dev;
83 		fc->bos_dev = 0;
84 
85 		/* add it to the folder */
86 		listInsert( root.head.next, (LINKABLE*)fc);
87 	}
88 
89 	listInit( &root_dev);
90 
91 	{ /* create the x:\dev\phys folder */
92 		fc = malloc(sizeof(FCOOKIE));
93 		fc->name = strdup("bos");
94 		fc->attr = FA_DIR;
95 		fc->folder = &root_dev_phys;
96 		fc->bos_dev = 0;
97 
98 		/* add it to the folder */
99 		listInsert( root_dev.head.next, (LINKABLE*)fc);
100 	}
101 
102 	listInit( &root_dev_phys);
103 
104 	for (i='A'; i<='Z'; i++) if (metainit.drives_map & (1<<(i-'A'))) {
105 		metaopen_t metaopen;
106 		int handle;
107 		char name[] = "A";
108 		name[0] = i;
109 
110 		fc = malloc(sizeof(FCOOKIE));
111 		fc->name = strdup(name);
112 		fc->attr = 0;
113 		fc->folder = NULL;
114 		fc->bos_dev = i;
115 		fc->bos_info_flags = BOS_INFO_DEVHIDDEN; /* by default hide from U:\dev */
116 
117 		DEBUG(("dev: %s->%s\n", name, fc->name));
118 
119 		/* attempt to get the bos_info */
120 		handle = Metaopen(i, &metaopen);
121 		if (handle == 0) {
122 			bos_info_t info;
123 			if ( ! Metaioctl(i, METADOS_IOCTL_MAGIC, METADOS_IOCTL_BOSINFO, &info)) {
124 				DEBUG(("ioctl: %s->%s %lx\n", name, fc->name, info.flags));
125 				fc->bos_info_flags = info.flags;
126 			}
127 			Metaclose(i);
128 
129 			DEBUG(("dev: %s->%s %lx\n", name, fc->name, fc->bos_info_flags));
130 
131 			/* the BOSINFO states that the device should not be visible
132 			 * in x:\dev\bos nor in x:\dev\bos */
133 			if ( fc->bos_info_flags & BOS_INFO_BOSHIDDEN ) {
134 				release_cookie( fc );
135 				continue;
136 			}
137 
138 			/* insert the devices that have a decent name also to u:\dev */
139 			if ( ! (fc->bos_info_flags & BOS_INFO_DEVHIDDEN) && *metaopen.name ) {
140 				FCOOKIE *cfc = dup_cookie(fc);
141 				free( cfc->name);
142 				cfc->name = strdup(metaopen.name);
143 				listInsert( &root_dev.tail, (LINKABLE*)cfc);
144 			}
145 		}
146 
147 		/* add it to the folder */
148 		listInsert( root_dev_phys.head.next, (LINKABLE*)fc);
149 	}
150 
151 	return 0;
152 }
153 
154 
155 long
getxattr(FCOOKIE * fc,struct xattr * res)156 getxattr (FCOOKIE *fc, struct xattr *res)
157 {
158 	res->mode = 0666;
159         res->mode |= fc->attr & FA_DIR ? (S_IFDIR|0111) : 0;
160 
161 	res->index = (long)fc;
162 	res->dev = (long)&root;
163 	res->rdev = (long)&root;
164 	res->nlink = 1;
165 	res->uid = 0;
166 	res->gid = 0;
167 	res->size = 0;
168 	res->blksize = 512;
169 	res->nblocks = ( res->size + res->blksize - 1) >> 9;
170 	// FIXME!
171 	res->mtime = 0;
172 	res->mdate = 0;
173 	res->atime = 0;
174 	res->adate = 0;
175 	res->ctime = 0;
176 	res->cdate = 0;
177 	res->attr = fc->attr;
178 	res->reserved2 = 0;
179 	res->reserved3[0] = 0;
180 	res->reserved3[1] = 0;
181 	return 0;
182 }
183 
184 
185 long
name2cookie(LIST * folder,const char * name,FCOOKIE ** res)186 name2cookie (LIST *folder, const char *name, FCOOKIE **res)
187 {
188 	char lowname[32];
189 	FCOOKIE* fc;
190 
191 	DEBUG(( "name2cookie: name=%s\n", name));
192 
193 	/* look for 'name' in the folder */
194 	listForEach( FCOOKIE*, fc, folder) {
195 		char *c = lowname;
196 		char *f = fc->name;
197 		while ( (*c++ = tolower(*f++)) ) ;
198 
199 		DEBUG(( "name2cookie: fc->name=%s\n", fc->name));
200 		if ( ! strcmp( lowname, name) ) {
201 			*res = fc;
202 			return 0;
203 		}
204 	}
205 
206 	return -ENOENT;
207 }
208 
209 /*
210  * routines for parsing path names
211  */
212 
213 /*
214  * relpath2cookie converts a TOS file name into a file cookie representing
215  * the directory the file resides in, and a character string representing
216  * the name of the file in that directory. The character string is
217  * copied into the "lastname" array. If lastname is NULL, then the cookie
218  * returned actually represents the file, instead of just the directory
219  * the file is in.
220  *
221  * note that lastname, if non-null, should be big enough to contain all the
222  * characters in "path", since if the file system doesn't want the kernel
223  * to do path name parsing we may end up just copying path to lastname
224  * and returning the current or root directory, as appropriate
225  *
226  * "dir" is the directory relative to which the search should start.
227  * if you just want the current directory, use path2cookie instead.
228  *
229  */
230 
231 # define DIRSEP(p)  (((p) == '\\') || ((p) == '/'))
232 
233 long
relpath2cookie(FCOOKIE * dir,const char * path,char * lastname,FCOOKIE ** res)234 relpath2cookie (FCOOKIE *dir, const char *path, char *lastname, FCOOKIE **res)
235 {
236 	long r = 0;
237 	short do_last = (lastname == NULL);
238 
239 	char temp[PATH_MAX];
240 	if ( ! lastname ) lastname = temp;
241 
242 	DEBUG(( "relpath2cookie: dir=%s path=%s\n", dir->name, path));
243 
244 	/* first, check for a drive letter
245 	 */
246 	if (path[1] == ':')
247 	{
248 		char c = tolower ((int)path[0] & 0xff);
249 		if (c >= 'a' && c <= 'z')
250 			path += 2;
251 		else if (c >= '1' && c <= '6')
252 			path += 2;
253 	}
254 
255 	while (*path)
256 	{
257 		/* now we must have a directory, since there are more things
258 		 * in the path
259 		 */
260 		if ( ! (dir->attr & FA_DIR) )
261 			return -ENOTDIR;
262 
263 		/*  skip slashes
264 		*/
265 		while (DIRSEP (*path))
266 			path++;
267 
268 		/* if there's nothing left in the path, we can break here
269 		 */
270 		if (!*path)
271 		{
272 			*res = dir;
273 			*lastname = '\0';
274 			return 0;
275 		}
276 
277 		/* next, peel off the next name in the path
278 		*/
279 		{
280 			register int len;
281 			register char c, *s;
282 
283 			len = 0;
284 			s = lastname;
285 			c = *path;
286 			while (c && !DIRSEP (c))
287 			{
288 				if (len++ < PATH_MAX)
289 					*s++ = tolower(c);
290 				c = *++path;
291 			}
292 
293 			*s = 0;
294 		}
295 
296 		/* if there are no more names in the path, and we don't want
297 		 * to actually look up the last name, then we're done
298 		 */
299 		if (!do_last && !*path)
300 		{
301 			*res = dir;
302 			return 0;
303 		}
304 
305 		r = name2cookie (dir->folder, lastname, res);
306 		if (r)
307 		{
308 			if (r == -ENOENT && *path)
309 			{
310 				/* the "file" we didn't find was treated as a directory */
311 				return -ENOTDIR;
312 			}
313 			return r;
314 		}
315 
316 		dir = *res;
317 	}
318 
319 	return 0;
320 }
321 
322 long
path2cookie(const char * path,char * lastname,FCOOKIE ** res)323 path2cookie (const char *path, char *lastname, FCOOKIE **res)
324 {
325 	static FCOOKIE rootfc;
326 	long r;
327 
328 	rootfc.name = "devdir:"; // FIXME: DEBUG!
329 	rootfc.attr = FA_DIR;
330 	rootfc.folder = &root;
331 	rootfc.bos_dev = 0;
332 	r  = relpath2cookie ( &rootfc, path, lastname, res);
333 	DEBUG(( "path2cookie: r=%d\n", r));
334 	return r;
335 }
336 
337 
338