9a189abe94dd22c5859cde7d895f2cc09f6e0b0b
[construo.git] / unix_system.cxx
blob9a189abe94dd22c5859cde7d895f2cc09f6e0b0b
1 // $Id: unix_system.cxx,v 1.15 2003/07/25 13:16:04 grumbel Exp $
2 //
3 // Construo - A wire-frame construction game
4 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <stdio.h>
21 #include <assert.h>
22 #include <unistd.h>
23 #include <sys/time.h>
24 #include <time.h>
25 #include <string>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #include <pwd.h>
30 #include <errno.h>
31 #include <iostream>
32 #include <algorithm>
33 #include "construo_error.hxx"
34 #include "string_utils.hxx"
35 #include "construo.hxx"
36 #include "path_manager.hxx"
37 #include "unix_system.hxx"
39 using namespace StringUtils;
41 UnixSystem::UnixSystem ()
42 { // riped out of ClanLib-0.7
43 timeval tv;
44 gettimeofday(&tv, NULL);
45 start_time = (long) tv.tv_sec*(long) 1000+(long) tv.tv_usec/(long) 1000;
47 char* home = getenv("HOME");
48 if (home)
50 construo_rc_path = std::string(home) + std::string("/.construo/");
52 else
54 std::cout << "UnixSystem: FATAL ERROR: couldn't find env variable $HOME" << std::endl;
55 throw ConstruoError ("UnixSystem: Couldn't find $HOME!");
58 // create $HOME directory if not already there
59 struct stat buf;
61 if (stat(construo_rc_path.c_str(), &buf) != 0) // Couldn't find directory, create it
63 if (mkdir(construo_rc_path.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) != 0)
65 throw ConstruoError(std::string("UnixSystem: ") + construo_rc_path + ": "
66 + strerror(errno));
69 else
71 if (S_ISDIR(buf.st_rdev)) // Is not a directory
73 throw ConstruoError("Error: " + construo_rc_path + " is not a directory!");
76 if (access(construo_rc_path.c_str (), R_OK | W_OK | X_OK) != 0) // not readable/writeable
78 throw ConstruoError("Error: " + construo_rc_path + " is not read or writeable!");
83 UnixSystem::~UnixSystem ()
87 unsigned int
88 UnixSystem::get_time ()
89 { // riped out of ClanLib-0.7
90 timeval tv;
91 gettimeofday(&tv, NULL);
93 long tid = (long) tv.tv_sec*(long) 1000 + (long) tv.tv_usec/(long) 1000 - start_time;
95 return tid;
98 void
99 UnixSystem::sleep (unsigned long t)
101 usleep (t);
104 std::string
105 UnixSystem::get_construo_rc_path()
107 std::cout << "Returning: \n" << construo_rc_path << std::endl;
108 return construo_rc_path;
111 std::string
112 UnixSystem::get_user_realname()
114 struct passwd* pw;
116 pw = getpwuid(getuid());
117 if (pw)
119 return pw->pw_gecos;
121 else
123 return "";
127 std::string
128 UnixSystem::get_user_email()
130 const char* s_email = getenv("EMAIL");
131 if (s_email)
133 return s_email;
135 else
136 return "";
139 unsigned int
140 UnixSystem::get_mtime (const std::string& filename)
142 std::string sys_name = translate_filename(filename);
144 struct stat buf;
145 if (stat(sys_name.c_str(), &buf) != 0)
147 return 0;
149 else
151 return buf.st_mtime;
155 FileType
156 UnixSystem::get_file_type(const std::string& filename)
158 if (filename == "/examples/"
159 || filename == "/user/")
160 return FT_DIRECTORY;
162 std::string sys_name = translate_filename(filename);
164 struct stat buf;
165 if (stat(sys_name.c_str(), &buf) != 0)
167 std::cout << "UnixSystem: ERROR: Couldn't stat: '" << sys_name << "'" << std::endl;
168 return FT_UNKNOWN_FILE;
170 else
172 if (S_ISDIR(buf.st_mode))
174 return FT_DIRECTORY;
176 else if (S_ISREG(buf.st_mode))
178 if (has_suffix(filename, ".construo") || has_suffix(filename, ".construo.gz"))
179 return FT_CONSTRUO_FILE;
180 else
182 return FT_UNKNOWN_FILE;
185 else
187 return FT_UNKNOWN_FILE;
192 std::string
193 UnixSystem::translate_filename (const std::string& filename)
195 if (filename == "/")
197 assert("root directory is not translatable");
198 return "";
200 else if (has_prefix(filename, "/user/"))
202 return construo_rc_path + filename.substr(6);
204 else if (has_prefix(filename, "/examples/"))
206 return path_manager.complete("examples/") + filename.substr(10);
208 else
209 return filename;
212 FILE*
213 UnixSystem::open_input_file(const std::string& filename)
215 std::cout << "UnixSystem: open_input_file: " << translate_filename (filename) << std::endl;
216 return fopen(translate_filename (filename).c_str(), "r");
219 FILE*
220 UnixSystem::open_output_file(const std::string& filename)
222 std::cout << "UnixSystem: open_output_file: " << translate_filename (filename) << std::endl;
223 return fopen(translate_filename (filename).c_str(), "w");
227 /** Sort directories before files and sort them all
228 alphabetically */
229 struct DirectorySorter
231 std::string pathname;
233 DirectorySorter(const std::string& p)
234 : pathname(p)
238 bool operator()(const std::string& lhs, const std::string& rhs)
240 FileType lhs_type = system_context->get_file_type(pathname + "/" + lhs);
241 FileType rhs_type = system_context->get_file_type(pathname + "/" + rhs);
243 if (lhs_type == rhs_type)
244 return (lhs < rhs);
245 else if (lhs_type == FT_DIRECTORY)
247 return true;
249 else if (rhs_type == FT_DIRECTORY)
251 return false;
253 else
255 return (lhs < rhs);
260 std::vector<std::string>
261 UnixSystem::read_directory(const std::string& arg_pathname)
263 if (arg_pathname == "/")
265 std::vector<std::string> ret;
266 ret.push_back("examples/");
267 ret.push_back("user/");
268 return ret;
270 else
272 std::vector<std::string> dir_lst;
273 std::string pathname = translate_filename (arg_pathname);
275 DIR* dir = ::opendir (pathname.c_str());
277 if (!dir)
279 std::cout << "UnixSystem: Error couldn't open: '" << pathname << "', ignoring\n"
280 << " error and continuing with an empty directory" << std::endl;
282 else
284 struct dirent* entry;
286 while ((entry = readdir(dir)) != 0)
288 if (strcmp(entry->d_name, ".") != 0
289 && strcmp(entry->d_name, "..") != 0
290 && strcmp(entry->d_name, "CVS") != 0)
291 { // We ignore unusefull directories
292 dir_lst.push_back(entry->d_name);
296 closedir (dir);
299 std::sort(dir_lst.begin(), dir_lst.end(), DirectorySorter(pathname));
301 return dir_lst;
305 /* EOF */