summaryrefslogtreecommitdiffstats
path: root/Mac/Compat/opendir.c
blob: a015609a186df5bfa446f1aab1becd9e8346fa94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Macintosh version of UNIX directory access package
 * (opendir, readdir, closedir).
 * Public domain by Guido van Rossum, CWI, Amsterdam (July 1987).
 */

#include "dirent.h"
#include "macdefs.h"

static DIR opened;

/*
 * Open a directory.  This means calling PBOpenWD.
 * The value returned is always the address of opened, or NULL.
 * (I have as yet no use for multiple open directories; this could
 * be implemented by allocating memory dynamically.)
 */

DIR *
opendir(path)
	char *path;
{
#if TARGET_API_MAC_CARBON
	Str255 ppath;
	FSSpec fss;
	int plen;
	OSErr err;
	
	if (opened.nextfile != 0) {
		errno = EBUSY;
		return NULL; /* A directory is already open. */
	}
	plen = strlen(path);
	c2pstrcpy(ppath, path);
	if ( ppath[plen] != ':' )
		ppath[++plen] = ':';
	ppath[++plen] = 'x';
	ppath[0] = plen;
	if( (err = FSMakeFSSpec(0, 0, ppath, &fss)) < 0 && err != fnfErr ) {
		errno = EIO;
		return NULL;
	}
	opened.dirid = fss.parID;
	opened.vrefnum = fss.vRefNum;
	opened.nextfile = 1;
	return &opened;
#else
	union {
		WDPBRec d;
		VolumeParam v;
	} pb;
	char ppath[MAXPATH];
	short err;
	
	if (opened.nextfile != 0) {
		errno = EBUSY;
		return NULL; /* A directory is already open. */
	}
	strncpy(ppath+1, path, ppath[0]= strlen(path));
	pb.d.ioNamePtr= (unsigned char *)ppath;
	pb.d.ioVRefNum= 0;
	pb.d.ioWDProcID= 0;
	pb.d.ioWDDirID= 0;
	err= PBOpenWD((WDPBPtr)&pb, 0);
	if (err != noErr) {
		errno = ENOENT;
		return NULL;
	}
	opened.dirid= pb.d.ioVRefNum;
	opened.nextfile= 1;
	return &opened;
#endif
}

/*
 * Close a directory.
 */

void
closedir(dirp)
	DIR *dirp;
{
#if TARGET_API_MAC_CARBON
	dirp->nextfile = 0;
#else
	WDPBRec pb;
	
	pb.ioVRefNum= dirp->dirid;
	(void) PBCloseWD(&pb, 0);
	dirp->dirid= 0;
	dirp->nextfile= 0;
#endif
}

/*
 * Read the next directory entry.
 */

struct dirent *
readdir(dp)
	DIR *dp;
{
	union {
		DirInfo d;
		FileParam f;
		HFileInfo hf;
	} pb;
	short err;
	static struct dirent dir;
	
	dir.d_name[0]= 0;
	pb.d.ioNamePtr= (unsigned char *)dir.d_name;
#if TARGET_API_MAC_CARBON
	pb.d.ioVRefNum= dp->vrefnum;
	pb.d.ioDrDirID= dp->dirid;
#else
	pb.d.ioVRefNum= dp->dirid;
	pb.d.ioDrDirID= 0;
#endif
	pb.d.ioFDirIndex= dp->nextfile++;
	err= PBGetCatInfo((CInfoPBPtr)&pb, 0);
	if (err != noErr) {
		errno = EIO;
		return NULL;
	}
#if TARGET_API_MAC_CARBON
	p2cstrcpy(dir.d_name, (StringPtr)dir.d_name);
#else
	(void) p2cstr((unsigned char *)dir.d_name);
#endif
	return &dir;
}