home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
mint
/
mntlib16.lzh
/
MNTLIB16
/
DIRENT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-03
|
4KB
|
196 lines
/* opendir/readdir/closedir routines */
/* under MiNT (v0.9 or better) these use the appropriate system calls.
* under TOS or older versions of MiNT, they use Fsfirst/Fsnext
*
* Written by Eric R. Smith and placed in the public domain
*/
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <limits.h>
#include <dirent.h>
#include <errno.h>
#include <osbind.h>
#include <mintbind.h>
#include "lib.h"
extern int __mint;
extern ino_t __inode; /* in stat.c */
DIR *
opendir(uname)
const char *uname;
{
DIR *d;
long r, olddta;
char name[PATH_MAX];
char dirpath[PATH_MAX];
_unx2dos(uname, name);
if (__mint > 8) {
r = Dopendir(name, 0);
if ( (r & 0xff000000) == 0xff000000 ) {
errno = -r;
return 0;
}
return (DIR *)r;
}
/* TOS emulation routines */
d = malloc(sizeof(DIR));
if (!d) {
errno = ENOMEM;
return d;
}
strcat(name, "\\*.*");
olddta = Fgetdta();
Fsetdta(d->dta);
r = Fsfirst(name, 0xff);
Fsetdta(olddta);
if (r == 0) {
d->status = _STARTSEARCH;
} else if (r == -ENOENT) {
d->status = _NMFILE;
} else {
free(d);
errno = -r;
return 0;
}
d->buf.d_off = 0;
/* for rewinddir: if necessary, build a relative path */
if (name[1] == ':') { /* absolute path, no problem */
dirpath[0] = 0;
} else {
dirpath[0] = Dgetdrv() + 'A';
dirpath[1] = ':';
dirpath[2] = 0;
if (*name != '\\')
(void)Dgetpath(dirpath+2, 0);
}
d->dirname = malloc(strlen(dirpath)+strlen(name)+1);
if (d->dirname) {
strcpy(d->dirname, dirpath);
strcat(d->dirname, name);
}
return d;
}
struct dirent *
readdir(d)
DIR *d;
{
struct dbuf {
long ino;
char name[NAME_MAX + 1];
} dbuf;
long r, olddta;
struct dirent *dd = &d->buf;
if (__mint > 8) {
r = Dreaddir(NAME_MAX+1+sizeof(long), d, &dbuf);
if (r == -ENMFIL)
return 0;
else if (r) {
errno = -r;
return 0;
}
dd->d_ino = dbuf.ino;
dd->d_off++;
dd->d_reclen = strlen(dbuf.name);
strcpy(dd->d_name, dbuf.name);
return dd;
}
/* ordinary TOS search, using Fsnext. Note that the first time through,
* Fsfirst has already provided valid data for us; for subsequent
* searches, we need Fsnext.
*/
if (d->status == _NMFILE)
return 0;
if (d->status == _STARTSEARCH) {
d->status = _INSEARCH;
} else {
olddta = Fgetdta();
Fsetdta(&d->dta);
r = Fsnext();
Fsetdta(olddta);
if (r == -ENMFIL) {
d->status = _NMFILE;
return 0;
} else if (r) {
errno = -r;
return 0;
}
}
dd->d_ino = __inode++;
dd->d_off++;
_dos2unx(d->dta+30, dd->d_name);
dd->d_reclen = strlen(dd->d_name);
return dd;
}
void
rewinddir(dirp)
DIR *dirp;
{
long r, olddta;
if (__mint >= 9) {
(void)Drewinddir(dirp);
return;
}
/* I wish POSIX had allowed an error to occur here! */
if (!dirp->dirname) {
return;
}
olddta = Fgetdta();
Fsetdta(dirp->dta);
r = Fsfirst(dirp->dirname, 0xff);
Fsetdta(olddta);
if (r == 0) {
dirp->status = _STARTSEARCH;
} else {
dirp->status = _NMFILE;
}
dirp->buf.d_off = 0;
}
int
closedir(dirp)
DIR *dirp;
{
if (__mint > 8) {
return Dclosedir(dirp);
}
free(dirp);
return 0;
}
/* the next two aren't POSIX, but lots of people have them */
off_t
telldir(dirp)
DIR *dirp;
{
return dirp->buf.d_off;
}
void
seekdir(dirp, loc)
DIR *dirp;
off_t loc;
{
rewinddir(dirp);
while (dirp->buf.d_off != loc) {
if (!readdir(dirp))
break;
}
}