1 /*
2  *  ppui/osinterface/posix/PPPath_POSIX.cpp
3  *
4  *  Copyright 2009 Peter Barth
5  *
6  *  This file is part of Milkytracker.
7  *
8  *  Milkytracker is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  Milkytracker is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 /*
24  *  PPPath_POSIX.cpp
25  *  MilkyTracker
26  *
27  *  Created by Peter Barth on 10.03.06.
28  *
29  */
30 
31 #include "PPPath_POSIX.h"
32 #include <sys/stat.h>
33 #include <limits.h>
34 
35 #ifdef __PSP__
36 // Needed for PATH_MAX
37 #include <sys/syslimits.h>
38 #endif
39 
40 #ifdef PATH_MAX
41 #define PPMAX_DIR_PATH PATH_MAX
42 #else
43 #define PPMAX_DIR_PATH 1024
44 #endif
45 
create(const PPSystemString & path,const PPSystemString & name)46 void PPPathEntry_POSIX::create(const PPSystemString& path, const PPSystemString& name)
47 {
48 	this->name = name;
49 	PPSystemString fullPath = path;
50 
51 	fullPath.append(name);
52 
53 	struct stat file_status;
54 
55 	if (::stat(fullPath, &file_status) == 0)
56 	{
57 		size = file_status.st_size;
58 
59 		if (S_ISDIR(file_status.st_mode))
60 			type = Directory;
61 		//if (S_ISLNK(file_status.st_mode))
62 		//	printf("foo.txt is a symbolic link\n");
63 		if (S_ISCHR(file_status.st_mode))
64 			type = Hidden;
65 		if (S_ISBLK(file_status.st_mode))
66 			type = Hidden;
67 		if (S_ISFIFO(file_status.st_mode))
68 			type = Hidden;
69 		if (S_ISSOCK(file_status.st_mode))
70 			type = Hidden;
71 		if (S_ISREG(file_status.st_mode))
72 			type = File;
73 	}
74 	else
75 	{ /* stat() call failed and returned '-1'. */
76 		type = Nonexistent;
77 	}
78 }
79 
isHidden() const80 bool PPPathEntry_POSIX::isHidden() const
81 {
82 	return PPPathEntry::isHidden() || (name.startsWith(".") && name.compareTo("..") != 0);
83 }
84 
updatePath()85 bool PPPath_POSIX::updatePath()
86 {
87 	return chdir(current) == 0;
88 }
89 
PPPath_POSIX()90 PPPath_POSIX::PPPath_POSIX()
91 {
92 	current = getCurrent();
93 	updatePath();
94 }
95 
PPPath_POSIX(const PPSystemString & path)96 PPPath_POSIX::PPPath_POSIX(const PPSystemString& path) :
97 	current(path)
98 {
99 	updatePath();
100 }
101 
getCurrent()102 const PPSystemString PPPath_POSIX::getCurrent()
103 {
104 	char cwd[PPMAX_DIR_PATH+1];
105 	memset(cwd, 0, sizeof(cwd));
106 
107 	getcwd(cwd, PPMAX_DIR_PATH+1);
108 
109 	PPSystemString path(cwd);
110 
111 	path.ensureTrailingCharacter(getPathSeparatorAsASCII());
112 	return path;
113 }
114 
change(const PPSystemString & path)115 bool PPPath_POSIX::change(const PPSystemString& path)
116 {
117 	PPSystemString old = current;
118 	current = path;
119 	current.ensureTrailingCharacter(getPathSeparatorAsASCII());
120 	bool res = updatePath();
121 	if (res)
122 		return true;
123 	current = old;
124 	return false;
125 }
126 
stepInto(const PPSystemString & directory)127 bool PPPath_POSIX::stepInto(const PPSystemString& directory)
128 {
129 	PPSystemString old = current;
130 	current.append(directory);
131 	current.append(getPathSeparator());
132 	bool res = updatePath();
133 	if (res)
134 		return true;
135 	current = old;
136 	return false;
137 }
138 
getFirstEntry()139 const PPPathEntry* PPPath_POSIX::getFirstEntry()
140 {
141 	dir = ::opendir(current);
142 	if (!dir)
143 	{
144 		return NULL;
145 	}
146 
147 	return getNextEntry();
148 }
149 
getNextEntry()150 const PPPathEntry* PPPath_POSIX::getNextEntry()
151 {
152 	struct dirent* entry;
153 	if ((entry = ::readdir(dir)) != NULL)
154 	{
155 		PPSystemString file(entry->d_name);
156 		this->entry.create(current, file);
157 
158 		return &this->entry;
159 	}
160 
161 	::closedir(dir);
162 	return NULL;
163 }
164 
canGotoHome() const165 bool PPPath_POSIX::canGotoHome() const
166 {
167 	return getenv("HOME") ? true : false;
168 }
169 
gotoHome()170 void PPPath_POSIX::gotoHome()
171 {
172 	char* home = getenv("HOME");
173 	if (home)
174 	{
175 		change(home);
176 		updatePath();
177 	}
178 }
179 
canGotoRoot() const180 bool PPPath_POSIX::canGotoRoot() const
181 {
182 	return true;
183 }
184 
gotoRoot()185 void PPPath_POSIX::gotoRoot()
186 {
187 	change("/");
188 	updatePath();
189 }
190 
canGotoParent() const191 bool PPPath_POSIX::canGotoParent() const
192 {
193 	return true;
194 }
195 
gotoParent()196 void PPPath_POSIX::gotoParent()
197 {
198 	stepInto("..");
199 }
200 
getPathSeparatorAsASCII() const201 char PPPath_POSIX::getPathSeparatorAsASCII() const
202 {
203 	return '/';
204 }
205 
getPathSeparator() const206 const PPSystemString PPPath_POSIX::getPathSeparator() const
207 {
208 	return PPSystemString(getPathSeparatorAsASCII());
209 }
210 
fileExists(const PPSystemString & fileName) const211 bool PPPath_POSIX::fileExists(const PPSystemString& fileName) const
212 {
213 	struct stat file_status;
214 
215 	if (::stat(fileName, &file_status) == 0)
216 	{
217 		return (S_ISREG(file_status.st_mode)) != 0;
218 	}
219 
220 	return false;
221 }
222 
223 
224