1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #if defined(__WII__)
24 
25 #define FORBIDDEN_SYMBOL_EXCEPTION_time_h
26 #define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
27 
28 #define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
29 
30 #include "backends/fs/wii/wii-fs.h"
31 #include "backends/fs/wii/wii-fs-factory.h"
32 #include "backends/fs/stdiostream.h"
33 
34 #include <sys/iosupport.h>
35 #include <sys/dir.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <errno.h>
39 #include <unistd.h>
40 
41 #include <gctypes.h>
42 
43 // gets all registered devoptab devices
getDevopChildren(AbstractFSList & list,ListMode mode,bool hidden) const44 bool WiiFilesystemNode::getDevopChildren(AbstractFSList &list, ListMode mode, bool hidden) const {
45 	u8 i;
46 	const devoptab_t* dt;
47 
48 	if (mode == Common::FSNode::kListFilesOnly)
49 		return true;
50 
51 	// skip in, out and err
52 	for (i = 3; i < STD_MAX; ++i) {
53 		dt = devoptab_list[i];
54 
55 		if (!dt || !dt->name || !dt->open_r || !dt->diropen_r)
56 			continue;
57 
58 		list.push_back(new WiiFilesystemNode(Common::String(dt->name) + ":/"));
59 	}
60 
61 	return true;
62 }
63 
initRootNode()64 void WiiFilesystemNode::initRootNode() {
65 	_path.clear();
66 	_displayName = "<devices>";
67 
68 	_exists = true;
69 	_isDirectory = true;
70 	_isReadable = false;
71 	_isWritable = false;
72 }
73 
clearFlags()74 void WiiFilesystemNode::clearFlags() {
75 	_exists = false;
76 	_isDirectory = false;
77 	_isReadable = false;
78 	_isWritable = false;
79 }
80 
setFlags(const struct stat * st)81 void WiiFilesystemNode::setFlags(const struct stat *st) {
82 	_exists = true;
83 	_isDirectory = ( (st->st_mode & S_IFDIR) != 0 );
84 	_isReadable = ( (st->st_mode & S_IRUSR) != 0 );
85 	_isWritable = ( (st->st_mode & S_IWUSR) != 0 );
86 }
87 
WiiFilesystemNode()88 WiiFilesystemNode::WiiFilesystemNode() {
89 	initRootNode();
90 }
91 
WiiFilesystemNode(const Common::String & p)92 WiiFilesystemNode::WiiFilesystemNode(const Common::String &p) {
93 	if (p.empty()) {
94 		initRootNode();
95 		return;
96 	}
97 
98 	_path = Common::normalizePath(p, '/');
99 
100 	WiiFilesystemFactory::instance().mountByPath(_path);
101 
102 	// "sd:" is not a valid directory, but "sd:/" is
103 	if (_path.lastChar() == ':')
104 		_path += '/';
105 
106 	_displayName = lastPathComponent(_path, '/');
107 
108 	struct stat st;
109 	if(stat(_path.c_str(), &st) != -1)
110 		setFlags(&st);
111 	else
112 		clearFlags();
113 }
114 
WiiFilesystemNode(const Common::String & p,const struct stat * st)115 WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, const struct stat *st) {
116 	if (p.empty()) {
117 		initRootNode();
118 		return;
119 	}
120 
121 	_path = Common::normalizePath(p, '/');
122 
123 	// "sd:" is not a valid directory, but "sd:/" is
124 	if (_path.lastChar() == ':')
125 		_path += '/';
126 
127 	_displayName = lastPathComponent(_path, '/');
128 
129 	setFlags(st);
130 }
131 
exists() const132 bool WiiFilesystemNode::exists() const {
133 	return _exists;
134 }
135 
getChild(const Common::String & n) const136 AbstractFSNode *WiiFilesystemNode::getChild(const Common::String &n) const {
137 	assert(_isDirectory);
138 
139 	assert(!n.contains('/'));
140 
141 	Common::String newPath(_path);
142 	if (newPath.lastChar() != '/')
143 		newPath += '/';
144 	newPath += n;
145 
146 	return new WiiFilesystemNode(newPath);
147 }
148 
getChildren(AbstractFSList & list,ListMode mode,bool hidden) const149 bool WiiFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const {
150 	assert(_isDirectory);
151 
152 	if (_path.empty())
153 		return getDevopChildren(list, mode, hidden);
154 
155 	DIR* dp = opendir (_path.c_str());
156 	DIR* tmpdir;
157 
158 	if (dp == NULL)
159 		return false;
160 
161 	struct dirent *pent;
162 
163 	while ((pent = readdir(dp)) != NULL) {
164 		if (strcmp(pent->d_name, ".") == 0 || strcmp(pent->d_name, "..") == 0)
165 			continue;
166 
167 		Common::String newPath(_path);
168 		if (newPath.lastChar() != '/')
169 		  newPath += '/';
170 		newPath += pent->d_name;
171 
172 		bool isDir = false;
173 		tmpdir = opendir(newPath.c_str());
174 		if(tmpdir)
175 		{
176 			isDir = true;
177 			closedir(tmpdir);
178 		}
179 
180 		if ((mode == Common::FSNode::kListFilesOnly && isDir) ||
181 			(mode == Common::FSNode::kListDirectoriesOnly && !isDir))
182 			continue;
183 
184 		struct stat st;
185 		st.st_mode = 0;
186 		st.st_mode |= ( isDir ? S_IFDIR : 0 );
187 		st.st_mode |= S_IRUSR;
188 		st.st_mode |= S_IWUSR;
189 
190 		list.push_back(new WiiFilesystemNode(newPath, &st));
191 	}
192 
193 	closedir(dp);
194 
195 	return true;
196 }
197 
getParent() const198 AbstractFSNode *WiiFilesystemNode::getParent() const {
199 	if (_path.empty())
200 		return NULL;
201 
202 	const char *start = _path.c_str();
203 	const char *end = lastPathComponent(_path, '/');
204 
205 	return new WiiFilesystemNode(Common::String(start, end - start));
206 }
207 
createReadStream()208 Common::SeekableReadStream *WiiFilesystemNode::createReadStream() {
209 	return StdioStream::makeFromPath(getPath(), false);
210 }
211 
createWriteStream()212 Common::WriteStream *WiiFilesystemNode::createWriteStream() {
213 	return StdioStream::makeFromPath(getPath(), true);
214 }
215 
createDirectory()216 bool WiiFilesystemNode::createDirectory() {
217 	warning("WiiFilesystemNode::createDirectory(): Not supported");
218 	return _exists && _isDirectory;
219 }
220 
221 #endif //#if defined(__WII__)
222