Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
48 KB
Referenced Files
None
Subscribers
None
diff --git a/util/file-system.cpp b/util/file-system.cpp
index d50d13b0..9bb9a8b2 100644
--- a/util/file-system.cpp
+++ b/util/file-system.cpp
@@ -1,757 +1,757 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
/* FIXME: replace with <winalleg.h> */
#ifdef _WIN32
#define BITMAP dummyBITMAP
#include <windows.h>
#undef BITMAP
#endif
#endif
#include <algorithm>
#include "funcs.h"
#include "file-system.h"
#include "thread.h"
#include "system.h"
#include "globals.h"
#include <dirent.h>
#include <sstream>
#include <exception>
#include <string>
#include <fstream>
#include <ostream>
#ifndef USE_ALLEGRO
/* some sfl symbols conflict with allegro */
#include "sfl/sfl.h"
#include "sfl/sfldir.h"
#endif
#ifdef _WIN32
#define _WIN32_IE 0x400
#include <shlobj.h>
#endif
using namespace std;
/* some filesystem access can only be done by one thread at a time. specifically, sfl
* has its own allocator that is meant to be used in a single-threaded manner.
* rather than try to add locks to sfl we just wrap all sfl calls with a lock.
*
* initialize() must be called to initialize this lock
*/
// Util::Thread::Lock lock;
namespace Path{
/* remove extra path separators (/) */
string sanitize(string path){
size_t double_slash = path.find("//");
while (double_slash != string::npos){
path.erase(double_slash, 1);
double_slash = path.find("//");
}
return path;
}
static int invert(int c){
if (c == '\\'){
return '/';
}
return c;
}
std::string invertSlashes(string str){
transform(str.begin(), str.end(), str.begin(), invert);
return str;
}
const string & Path::path() const {
return mypath;
}
bool Path::isEmpty() const {
return mypath.empty();
}
Path::~Path(){
}
Path::Path(){
}
Path::Path(const std::string & path):
mypath(sanitize(invertSlashes(path))){
}
Path::Path(const Path & path):
mypath(sanitize(invertSlashes(path.path()))){
}
RelativePath::RelativePath(){
}
RelativePath::RelativePath(const std::string & path):
Path(path){
if (! path.empty() && path[0] == '/'){
ostringstream out;
out << "Relative path '" << path << "' cannot start with a /. Only absolute paths can start with /";
throw Storage::IllegalPath(__FILE__, __LINE__, out.str());
}
}
/* a/b/c/d -> b/c/d */
std::string stripFirstDir(const std::string & str){
if (str.find("/") != std::string::npos || str.find( "\\") != std::string::npos){
std::string temp = str;
size_t rem = temp.find("/");
if (rem != std::string::npos){
return str.substr(rem+1,str.size());
}
rem = temp.find("\\");
if( rem != std::string::npos ){
return str.substr(rem+1,str.size());
}
}
return str;
}
static vector<string> splitPath(string path){
vector<string> all;
if (path.size() > 0 && path[0] == '/'){
all.push_back("/");
}
size_t found = path.find('/');
while (found != string::npos){
if (found > 0){
all.push_back(path.substr(0, found));
}
path.erase(0, found + 1);
found = path.find('/');
}
if (path.size() != 0){
all.push_back(path);
}
return all;
}
static string joinPath(const vector<string> & paths){
ostringstream out;
bool first = true;
for (vector<string>::const_iterator it = paths.begin(); it != paths.end(); it++){
if (!first){
out << '/';
}
out << *it;
first = false;
}
return out.str();
}
/* a/b/c/d -> a/b/c
* a/b/c/d/ -> a/b/c
*/
static string dirname(string path){
vector<string> paths = splitPath(path);
if (paths.size() > 1){
paths.pop_back();
return joinPath(paths);
} else if (paths.size() == 1){
if (paths[0] == "/"){
return "/";
}
return ".";
} else {
return ".";
}
/*
while (path.size() > 0 && path[path.size() - 1] == '/'){
path.erase(path.size() - 1);
}
if (path.find("/") != string::npos ||
path.find("\\") != string::npos){
size_t rem = path.find_last_of("/");
if (rem != string::npos){
return path.substr(0, rem + 1);
}
rem = path.find_last_of("\\");
if (rem != string::npos){
return path.substr(0, rem + 1);
}
}
return "";
*/
}
RelativePath::RelativePath(const RelativePath & path):
Path(path){
}
RelativePath RelativePath::removeFirstDirectory() const {
return RelativePath(stripFirstDir(path()));
}
bool RelativePath::isFile() const {
vector<string> paths = splitPath(path());
return paths.size() == 1;
}
RelativePath RelativePath::firstDirectory() const {
vector<string> paths = splitPath(path());
if (paths.size() > 1){
return RelativePath(paths[0]);
}
return RelativePath();
}
RelativePath RelativePath::getDirectory() const {
return RelativePath(dirname(path()));
}
RelativePath RelativePath::getFilename() const {
return RelativePath(stripDir(path()));
}
bool RelativePath::operator<(const RelativePath & path) const {
return this->path() < path.path();
}
bool RelativePath::operator==(const RelativePath & path) const {
return this->path() == path.path();
}
RelativePath RelativePath::join(const RelativePath & him) const {
return RelativePath(path() + "/" + him.path());
}
RelativePath & RelativePath::operator=(const RelativePath & copy){
setPath(copy.path());
return *this;
}
AbsolutePath::AbsolutePath(){
}
AbsolutePath::AbsolutePath(const std::string & path):
Path(path){
}
AbsolutePath::AbsolutePath(const AbsolutePath & path):
Path(path){
}
AbsolutePath & AbsolutePath::operator=(const AbsolutePath & copy){
setPath(copy.path());
return *this;
}
bool AbsolutePath::operator==(const AbsolutePath & path) const {
return this->path() == path.path();
}
bool AbsolutePath::operator<(const AbsolutePath & path) const {
return this->path() < path.path();
}
AbsolutePath AbsolutePath::getDirectory() const {
return AbsolutePath(dirname(path()));
}
AbsolutePath AbsolutePath::getFilename() const {
return AbsolutePath(stripDir(path()));
}
AbsolutePath AbsolutePath::join(const RelativePath & path) const {
return AbsolutePath(this->path() + "/" + path.path());
}
InsensitivePath::InsensitivePath(const Path & what):
Path(what){
}
bool InsensitivePath::operator==(const Path & path) const {
return Util::upperCaseAll(this->path()) == Util::upperCaseAll(path.path());
}
std::string removeExtension(const std::string & str){
if (str.find(".") != std::string::npos){
return str.substr(0, str.find_last_of("."));
}
return str;
}
/* a/b/c/d -> d */
std::string stripDir(const std::string & str){
- if (str.find("/") != std::string::npos || str.find( "\\") != std::string::npos){
+ if (str.find("/") != std::string::npos || str.find("\\") != std::string::npos){
std::string temp = str;
size_t rem = temp.find_last_of( "/" );
if (rem != std::string::npos){
return str.substr(rem+1,str.size());
}
rem = temp.find_last_of( "\\" );
if( rem != std::string::npos ){
return str.substr(rem+1,str.size());
}
}
return str;
}
/* a/b/c/d -> a/b/c/ */
std::string stripFilename(const std::string & str){
std::string temp = str;
if( str.find( "/") != std::string::npos || str.find( "\\") != std::string::npos ){
size_t rem = temp.find_last_of( "/" );
if( rem != std::string::npos ){
return str.substr(0,rem+1);
}
rem = temp.find_last_of( "\\" );
if( rem != std::string::npos ){
return str.substr(0,rem+1);
}
}
return "";
}
}
namespace Storage{
Exception::Exception(const std::string & where, int line, const std::string & file):
Exc::Base(where, line),
reason(file){
}
Exception::Exception(const std::string & where, int line, const Exc::Base & nested, const std::string & file):
Exc::Base(where, line, nested),
reason(file){
}
Exception::Exception(const Exception & copy):
Exc::Base(copy),
reason(copy.reason){
}
Exception::~Exception() throw (){
}
const std::string Exception::getReason() const {
return reason;
}
NotFound::NotFound(const std::string & where, int line, const std::string & file):
Exception(where, line, file){
}
NotFound::NotFound(const std::string & where, int line, const Exc::Base & nested, const std::string & file):
Exception(where, line, nested, file){
}
NotFound::NotFound(const NotFound & copy):
Exception(copy){
}
NotFound::~NotFound() throw (){
}
IllegalPath::IllegalPath(const std::string & where, int line, const std::string & file):
Exception(where, line, file){
}
IllegalPath::IllegalPath(const std::string & where, int line, const Exc::Base & nested, const std::string & file):
Exception(where, line, nested, file){
}
IllegalPath::IllegalPath(const IllegalPath & copy):
Exception(copy){
}
IllegalPath::~IllegalPath() throw(){
}
System::System(){
}
System::~System(){
}
Util::ReferenceCount<System> self;
System & instance(){
if (self != NULL){
return *self;
}
self = new Filesystem(Util::getDataPath2());
return *self;
}
System & setInstance(const Util::ReferenceCount<System> & what){
self = what;
return *self;
}
/* will read upto 'length' bytes unless a null byte is seen first */
string EndianReader::readStringX(int length){
ostringstream out;
uint8_t letter = readByte1();
while (letter != 0 && length > 0){
out << letter;
letter = readByte1();
length -= 1;
}
return out.str();
}
/* unconditionally reads 'length' bytes */
std::string EndianReader::readString2(int length){
ostringstream out;
vector<uint8_t> bytes = readBytes(length);
for (vector<uint8_t>::iterator it = bytes.begin(); it != bytes.end(); it++){
char byte = *it;
if (byte == 0){
break;
}
out << *it;
}
return out.str();
}
void EndianReader::seekEnd(streamoff where){
stream.seekg(where, ios::end);
}
void EndianReader::seek(streampos where){
stream.seekg(where);
}
int EndianReader::position(){
return stream.tellg();
}
void EndianReader::readBytes(uint8_t * out, int length){
stream.read((char*) out, length);
}
vector<uint8_t> EndianReader::readBytes(int length){
vector<uint8_t> bytes;
for (int i = 0; i < length; i++){
uint8_t byte = 0;
stream.read((char*) &byte, 1);
if (stream.eof()){
throw Eof();
} else {
}
bytes.push_back(byte);
}
return bytes;
}
}
Filesystem::Filesystem(const AbsolutePath & path):
dataPath(path){
}
#ifdef _WIN32
Filesystem::AbsolutePath Filesystem::userDirectory(){
ostringstream str;
char path[MAX_PATH];
SHGetSpecialFolderPathA(0, path, CSIDL_APPDATA, false);
str << path << "/paintown/";
return Filesystem::AbsolutePath(str.str());
}
Filesystem::AbsolutePath Filesystem::configFile(){
ostringstream str;
char path[MAX_PATH];
SHGetSpecialFolderPathA(0, path, CSIDL_APPDATA, false);
str << path << "/paintown_configuration.txt";
return Filesystem::AbsolutePath(str.str());
}
#else
Filesystem::AbsolutePath Filesystem::configFile(){
ostringstream str;
/* what if HOME isn't set? */
str << getenv("HOME") << "/.paintownrc";
return Filesystem::AbsolutePath(str.str());
}
Filesystem::AbsolutePath Filesystem::userDirectory(){
ostringstream str;
char * home = getenv("HOME");
if (home == NULL){
str << "/tmp/paintown";
} else {
str << home << "/.paintown/";
}
return Filesystem::AbsolutePath(str.str());
}
#endif
Filesystem::AbsolutePath Filesystem::lookup(const RelativePath path){
vector<Filesystem::AbsolutePath> places;
#define push(x) try{ places.push_back(x); } catch (const Storage::IllegalPath & fail){ }
push(dataPath.join(path));
push(userDirectory().join(path));
push(Filesystem::AbsolutePath(path.path()));
#undef push
/* start error stuff early */
ostringstream out;
out << "Cannot find " << path.path() << ". I looked in ";
bool first = true;
for (vector<Filesystem::AbsolutePath>::iterator it = places.begin(); it != places.end(); it++){
Filesystem::AbsolutePath & final = *it;
if (::System::readable(final.path())){
return final;
}
if (!first){
out << ", ";
} else {
first = false;
}
out << "'" << final.path() << "'";
}
// out << "Cannot find " << path.path() << ". I looked in '" << dataPath.join(path).path() << "', '" << userDirectory().join(path).path() << "', and '" << path.path() << "'";
throw NotFound(__FILE__, __LINE__, out.str());
#if 0
/* first try the main data directory */
Filesystem::AbsolutePath final = dataPath.join(path);
if (::System::readable(final.path())){
return final;
}
/* then try the user directory, like ~/.paintown */
final = userDirectory().join(path);
if (::System::readable(final.path())){
return final;
}
/* then just look in the cwd */
if (::System::readable(path.path())){
return Filesystem::AbsolutePath(path.path());
}
ostringstream out;
out << "Cannot find " << path.path() << ". I looked in '" << dataPath.join(path).path() << "', '" << userDirectory().join(path).path() << "', and '" << path.path() << "'";
throw NotFound(__FILE__, __LINE__, out.str());
#endif
}
Filesystem::AbsolutePath Filesystem::lookupInsensitive(const Filesystem::AbsolutePath & directory, const Filesystem::RelativePath & path){
if (path.path() == ""){
throw NotFound(__FILE__, __LINE__, "Given empty path to lookup");
}
if (path.path() == "."){
return directory;
}
if (path.path() == ".."){
return directory.getDirectory();
}
if (path.isFile()){
vector<AbsolutePath> all = getFiles(directory, "*", true);
for (vector<AbsolutePath>::iterator it = all.begin(); it != all.end(); it++){
AbsolutePath & check = *it;
if (InsensitivePath(check.getFilename()) == path){
return check;
}
}
ostringstream out;
out << "Cannot find " << path.path() << " in " << directory.path();
throw NotFound(__FILE__, __LINE__, out.str());
} else {
return lookupInsensitive(lookupInsensitive(directory, path.firstDirectory()), path.removeFirstDirectory());
}
}
vector<Filesystem::AbsolutePath> Filesystem::findDirectoriesIn(const Filesystem::AbsolutePath & path){
vector<Filesystem::AbsolutePath> dirs;
DIR * dir = opendir(path.path().c_str());
if (dir == NULL){
return dirs;
}
struct dirent * entry = readdir(dir);
while (entry != NULL){
if (string(entry->d_name) != "." && string(entry->d_name) != ".."){
string total = path.path() + "/" + entry->d_name;
if (::System::isDirectory(total)){
dirs.push_back(AbsolutePath(total));
}
}
entry = readdir(dir);
}
closedir(dir);
return dirs;
}
vector<Filesystem::AbsolutePath> Filesystem::findDirectories(const RelativePath & path){
typedef vector<AbsolutePath> Paths;
Paths dirs;
Paths main_dirs = findDirectoriesIn(dataPath.join(path));
Paths user_dirs = findDirectoriesIn(userDirectory().join(path));
Paths here_dirs = findDirectoriesIn(Filesystem::AbsolutePath(path.path()));
dirs.insert(dirs.end(), main_dirs.begin(), main_dirs.end());
dirs.insert(dirs.end(), user_dirs.begin(), user_dirs.end());
dirs.insert(dirs.end(), here_dirs.begin(), here_dirs.end());
return dirs;
}
/* a/b/c/ -> a/b/c */
static string removeTrailingSlash(string str){
while (str.size() > 0 && str[str.size() - 1] == '/'){
str = str.erase(str.size() - 1);
}
return str;
}
vector<Filesystem::AbsolutePath> Filesystem::getFiles(const AbsolutePath & dataPath, const string & find, bool caseInsensitive){
#ifdef USE_ALLEGRO
struct al_ffblk info;
vector<AbsolutePath> files;
if ( al_findfirst( (dataPath.path() + "/" + find).c_str(), &info, FA_ALL ) != 0 ){
return files;
}
files.push_back(AbsolutePath(dataPath.path() + "/" + string(info.name)));
while ( al_findnext( &info ) == 0 ){
files.push_back(AbsolutePath(dataPath.path() + "/" + string(info.name)));
}
al_findclose( &info );
return files;
#else
Util::Thread::ScopedLock scoped(lock);
vector<AbsolutePath> files;
DIRST sflEntry;
// bool ok = open_dir(&sflEntry, removeTrailingSlash(dataPath.path()).c_str());
bool ok = open_dir(&sflEntry, dataPath.path().c_str());
if (!ok){
return files;
}
while (ok){
if (file_matches(sflEntry.file_name, find.c_str())){
files.push_back(AbsolutePath(dataPath.path() + "/" + string(sflEntry.file_name)));
}
ok = read_dir(&sflEntry);
}
close_dir(&sflEntry);
// Global::debug(0) << "Warning: Filesystem::getFiles() is not implemented yet for SDL" << endl;
return files;
#endif
}
template <class X>
static void append(vector<X> & destination, const vector<X> & source){
/*
for (typename vector<X>::const_iterator it = source.begin(); it != source.end(); it++){
destination.push_back(*it);
}
*/
copy(source.begin(), source.end(), back_insert_iterator<vector<X> >(destination));
}
vector<Filesystem::AbsolutePath> Filesystem::getAllDirectories(const AbsolutePath & path){
vector<AbsolutePath> all = findDirectoriesIn(path);
vector<AbsolutePath> final;
append(final, all);
for (vector<AbsolutePath>::iterator it = all.begin(); it != all.end(); it++){
vector<AbsolutePath> more = getAllDirectories(*it);
append(final, more);
}
return final;
}
vector<Filesystem::AbsolutePath> Filesystem::getFilesRecursive(const AbsolutePath & dataPath, const string & find, bool caseInsensitive){
if (!exists(dataPath)){
return vector<AbsolutePath>();
}
vector<AbsolutePath> directories = getAllDirectories(dataPath);
directories.push_back(dataPath);
vector<AbsolutePath> files;
for (vector<AbsolutePath>::iterator it = directories.begin(); it != directories.end(); it++){
vector<AbsolutePath> found = getFiles(*it, find, caseInsensitive);
append(files, found);
}
return files;
}
/*
std::string find(const std::string path){
if (path.length() == 0){
throw NotFound("No path given");
}
if (path[0] == '/'){
string str(path);
str.erase(0, 1);
string out = lookup(str);
if (System::isDirectory(out)){
return sanitize(out + "/");
}
return sanitize(out);
}
string out = lookup(path);
if (System::isDirectory(out)){
return sanitize(out + "/");
}
return sanitize(out);
}
*/
Filesystem::AbsolutePath Filesystem::find(const RelativePath & path){
if (path.isEmpty()){
throw NotFound(__FILE__, __LINE__, "No path given");
}
AbsolutePath out = lookup(path);
if (::System::isDirectory(out.path())){
return AbsolutePath(out.path() + "/");
}
return AbsolutePath(out.path());
}
Filesystem::AbsolutePath Filesystem::findInsensitive(const RelativePath & path){
try{
/* try sensitive lookup first */
return lookup(path);
} catch (const NotFound & fail){
}
/* get the base directory */
AbsolutePath directory = lookup(path.getDirectory());
return lookupInsensitive(directory, path.getFilename());
}
bool Filesystem::exists(const RelativePath & path){
try{
AbsolutePath absolute = find(path);
return true;
} catch (const NotFound & found){
return false;
}
}
bool Filesystem::exists(const AbsolutePath & path){
return ::System::readable(path.path());
}
Filesystem::RelativePath Filesystem::cleanse(const AbsolutePath & path){
string str = path.path();
if (str.find(dataPath.path()) == 0){
str.erase(0, dataPath.path().length());
} else if (str.find(userDirectory().path()) == 0){
str.erase(0, userDirectory().path().length());
}
return RelativePath(str);
}
diff --git a/util/nacl/network-system.cpp b/util/nacl/network-system.cpp
index 94d34b84..f395d086 100644
--- a/util/nacl/network-system.cpp
+++ b/util/nacl/network-system.cpp
@@ -1,808 +1,894 @@
#ifdef NACL
/* documentation for ppapi
* http://code.google.com/chrome/nativeclient/docs/reference/peppercpp/inherits.html
*/
/* issues with getting data
* 1. the function that starts the game is called from the main chrome thread
* which starts from a javascript call to module.PostMessage('run').
* ...
*
*/
#include <unistd.h>
#include <errno.h>
#include "network-system.h"
#include <sstream>
#include <fstream>
#include "../funcs.h"
#include "../debug.h"
+#include "../sfl/sfl.h"
#include <ppapi/c/pp_errors.h>
#include <ppapi/cpp/url_loader.h>
#include <ppapi/cpp/url_request_info.h>
#include <ppapi/cpp/url_response_info.h>
#include <ppapi/c/ppb_url_request_info.h>
#include <ppapi/cpp/completion_callback.h>
using std::string;
using std::map;
using std::vector;
using std::ostringstream;
using std::ifstream;
namespace Nacl{
static const char * CONTEXT = "nacl";
typedef Path::AbsolutePath AbsolutePath;
typedef Path::RelativePath RelativePath;
enum RequestType{
Exists
};
struct Request{
RequestType type;
AbsolutePath absolute;
RelativePath relative;
bool complete;
bool success;
};
Request operation;
struct NaclRequest{
virtual ~NaclRequest(){
}
virtual void start() = 0;
};
struct NaclRequestOpen: public NaclRequest {
NaclRequestOpen(pp::Instance * instance, const string & url, Manager * manager):
request(instance),
loader(instance),
url(url),
manager(manager){
request.SetURL(url);
request.SetMethod("GET");
// request.SetProperty(PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, pp::Var((bool) PP_TRUE));
}
void start(){
Global::debug(2) << "Request open for url " << url << std::endl;
pp::CompletionCallback callback(&NaclRequestOpen::onFinish, this);
int32_t ok = loader.Open(request, callback);
Global::debug(2) << "Open " << ok << std::endl;
if (ok != PP_OK_COMPLETIONPENDING){
// Global::debug(0) << "Call on main thread" << std::endl;
// core->CallOnMainThread(0, callback, ok);
callback.Run(ok);
}
// Global::debug(1) << "Callback running" << std::endl;
}
static void onFinish(void * me, int32_t result){
NaclRequestOpen * self = (NaclRequestOpen*) me;
self->finish(result);
}
void finish(int32_t result);
pp::URLRequestInfo request;
pp::URLLoader loader;
string url;
Manager * manager;
};
struct NaclRequestExists: public NaclRequest {
NaclRequestExists(pp::Instance * instance, const string & url, Manager * manager):
request(instance),
loader(instance),
url(url),
manager(manager){
request.SetURL(url);
request.SetMethod("GET");
}
void start(){
pp::CompletionCallback callback(&NaclRequestExists::onFinish, this);
int32_t ok = loader.Open(request, callback);
if (ok != PP_OK_COMPLETIONPENDING){
callback.Run(ok);
}
}
static void onFinish(void * me, int32_t result){
NaclRequestExists * self = (NaclRequestExists*) me;
self->finish(result);
}
void finish(int32_t result);
pp::URLRequestInfo request;
pp::URLLoader loader;
string url;
Manager * manager;
};
class FileHandle{
public:
FileHandle():
buffer(NULL){
}
~FileHandle(){
delete[] buffer;
}
class Reader{
public:
static const int PAGE_SIZE = 1024 * 32;
struct Page{
Page():
buffer(NULL),
size(0),
next(NULL){
buffer = new char[PAGE_SIZE];
}
char * buffer;
int size;
Page * next;
~Page(){
delete[] buffer;
delete next;
}
};
Reader(pp::CompletionCallback finish, pp::URLLoader & loader, FileHandle * handle, pp::Core * core):
finish(finish),
loader(loader),
handle(handle),
core(core),
tries(0){
current = &page;
}
int getSize(){
Page * use = &page;
int total = 0;
while (use != NULL){
total += use->size;
use = use->next;
}
return total;
}
void copy(char * buffer){
Page * use = &page;
while (use != NULL){
memcpy(buffer, use->buffer, use->size);
buffer += use->size;
use = use->next;
}
}
void read(){
pp::CompletionCallback callback(&Reader::onRead, this);
if (current->size == PAGE_SIZE){
Page * next = new Page();
current->next = next;
current = next;
}
int32_t ok = loader.ReadResponseBody(current->buffer + current->size, PAGE_SIZE - current->size, callback);
if (ok != PP_OK_COMPLETIONPENDING){
callback.Run(ok);
}
}
static void onRead(void * self, int32_t result){
Reader * reader = (Reader*) self;
reader->didRead(result);
}
void didRead(int32_t result){
Global::debug(2) << "Read " << result << " bytes" << std::endl;
current->size += result;
if (result > 0){
tries = 0;
read();
} else {
if (tries >= 3){
handle->readDone(this);
} else {
tries += 1;
pp::CompletionCallback callback(&Reader::doRead, this);
core->CallOnMainThread((tries - 1) * 25, callback, 0);
}
}
}
static void doRead(void * self, int32_t result){
Reader * reader = (Reader*) self;
reader->read();
}
pp::CompletionCallback finish;
pp::URLLoader & loader;
Page page;
Page * current;
FileHandle * handle;
pp::Core * core;
int tries;
};
void readAll(pp::CompletionCallback finish, pp::Core * core, pp::URLLoader & loader){
reader = new Reader(finish, loader, this, core);
reader->read();
}
void readDone(Reader * reader){
length = reader->getSize();
Global::debug(2) << "Done reading, got " << length << " bytes" << std::endl;
position = 0;
buffer = new char[length];
reader->copy(buffer);
reader->finish.Run(0);
}
int read(void * buffer, size_t count){
size_t bytes = position + count < length ? count : (length - position);
memcpy(buffer, this->buffer + position, bytes);
position += bytes;
return bytes;
}
off_t seek(off_t offset, int whence){
switch (whence){
case SEEK_SET: {
position = offset;
break;
}
case SEEK_CUR: {
position += offset;
break;
}
case SEEK_END: {
position = length - offset;
break;
}
}
return position;
}
off_t position;
off_t length;
char * buffer;
Util::ReferenceCount<Reader> reader;
};
class Manager{
public:
Manager(pp::Instance * instance, pp::Core * core):
instance(instance),
core(core),
factory(this){
}
pp::Instance * instance;
pp::Core * core;
Util::ReferenceCount<NaclRequest> request;
pp::CompletionCallbackFactory<Manager> factory;
struct OpenFileData{
const char * path;
Util::ReferenceCount<FileHandle> file;
};
struct ExistsData{
const char * path;
bool exists;
};
OpenFileData openFileData;
ExistsData existsData;
Util::Thread::LockObject lock;
volatile bool done;
Util::ReferenceCount<FileHandle> openFile(const char * path){
Global::debug(1, CONTEXT) << "open " << path << std::endl;
Util::Thread::ScopedLock scoped(lock);
done = false;
openFileData.path = path;
pp::CompletionCallback callback(&Manager::doOpenFile, this);
core->CallOnMainThread(0, callback, 0);
lock.wait(done);
return openFileData.file;
}
bool exists(const string & path){
Global::debug(1, CONTEXT) << "exists " << path << std::endl;
Util::Thread::ScopedLock scoped(lock);
done = false;
existsData.exists = false;
existsData.path = path.c_str();
pp::CompletionCallback callback(&Manager::doExists, this);
core->CallOnMainThread(0, callback, 0);
lock.wait(done);
return existsData.exists;
}
static void doExists(void * self, int32_t result){
Manager * manager = (Manager*) self;
manager->continueExists();
}
void continueExists(){
request = new NaclRequestExists(instance, existsData.path, this);
request->start();
}
void success(NaclRequestExists & exists){
existsData.exists = true;
requestComplete();
}
void failure(NaclRequestExists & exists){
existsData.exists = false;
requestComplete();
}
/* called by the main thread */
static void doOpenFile(void * self, int32_t result){
Manager * manager = (Manager*) self;
manager->continueOpenFile();
}
void continueOpenFile(){
request = new NaclRequestOpen(instance, openFileData.path, this);
request->start();
}
void requestComplete(){
/* destroy request on the main thread */
request = NULL;
lock.lockAndSignal(done, true);
}
void success(NaclRequestOpen & open){
pp::URLResponseInfo info = open.loader.GetResponseInfo();
if (info.GetStatusCode() == 200){
/*
int64_t received = 0;
int64_t total = 0;
if (open.loader.GetDownloadProgress(&received, &total)){
Global::debug(0) << "Downloaded " << received << " total " << total << std::endl;
}
*/
Util::ReferenceCount<FileHandle> handle = new FileHandle();
pp::CompletionCallback callback(&Manager::completeRead, this);
openFileData.file = handle;
handle->readAll(callback, core, open.loader);
/*
openFileData.file = nextFileDescriptor();
fileTable[openFileData.file] = new FileHandle(request.convert<NaclRequestOpen>());
readEntireFile(fileTable[openFileData.file]);
*/
} else {
Global::debug(1) << "Could not open file" << std::endl;
requestComplete();
}
}
static void completeRead(void * self, int32_t result){
Manager * manager = (Manager*) self;
manager->requestComplete();
}
void failure(NaclRequestOpen & open){
requestComplete();
}
};
void NaclRequestOpen::finish(int32_t result){
if (result == 0){
manager->success(*this);
} else {
manager->failure(*this);
}
}
void NaclRequestExists::finish(int32_t result){
if (result == 0){
pp::URLResponseInfo info = loader.GetResponseInfo();
if (info.GetStatusCode() == 200){
manager->success(*this);
} else {
manager->failure(*this);
}
} else {
manager->failure(*this);
}
}
+static void testMatchFile();
+
NetworkSystem::NetworkSystem(pp::Instance * instance, pp::Core * core):
instance(instance),
core(core){
+ // testMatchFile();
}
NetworkSystem::~NetworkSystem(){
}
AbsolutePath NetworkSystem::find(const RelativePath & path){
AbsolutePath all = Util::getDataPath2().join(path);
if (exists(all)){
return all;
}
throw Storage::NotFound(__FILE__, __LINE__, path.path());
}
RelativePath NetworkSystem::cleanse(const AbsolutePath & path){
string str = path.path();
if (str.find(Util::getDataPath2().path()) == 0){
str.erase(0, Util::getDataPath2().path().length());
} else if (str.find(userDirectory().path()) == 0){
str.erase(0, userDirectory().path().length());
}
return RelativePath(str);
}
bool NetworkSystem::exists(const RelativePath & path){
try{
AbsolutePath absolute = find(path);
return true;
} catch (const Storage::NotFound & found){
return false;
}
}
bool NetworkSystem::exists(const AbsolutePath & path){
Util::Thread::ScopedLock scoped(lock);
if (existsCache.find(path) != existsCache.end()){
return existsCache[path];
}
Manager manager(instance, core);
bool what = manager.exists(path.path());
existsCache[path] = what;
return what;
}
string NetworkSystem::readFileAsString(const AbsolutePath & path){
if (!exists(path)){
ostringstream fail;
fail << "Could not read " << path.path();
throw Filesystem::NotFound(__FILE__, __LINE__, fail.str());
}
ostringstream buffer;
ifstream input(path.path().c_str());
char stuff[1024];
while (input.good()){
input.read(stuff, sizeof(stuff) - 1);
- stuff[sizeof(stuff) - 1] = '\0';
+ int in = input.gcount();
+ stuff[in] = '\0';
buffer << stuff;
}
return buffer.str();
}
static vector<string> split(string input, char splitter){
vector<string> all;
size_t found = input.find(splitter);
while (found != string::npos){
all.push_back(input.substr(0, found));
input.erase(0, found + 1);
found = input.find(splitter);
}
if (input.size() != 0){
all.push_back(input);
}
return all;
}
vector<AbsolutePath> NetworkSystem::readDirectory(const AbsolutePath & dataPath){
/* assume existence of 'directory.txt' in the given directory */
AbsolutePath fullPath = dataPath.join(RelativePath("directory.txt"));
string all = readFileAsString(fullPath);
vector<string> files = split(all, '\n');
vector<AbsolutePath> paths;
for (vector<string>::iterator it = files.begin(); it != files.end(); it++){
string what = *it;
- paths.push_back(dataPath.join(RelativePath(what)));
+ if (what != ""){
+ paths.push_back(dataPath.join(RelativePath(what)));
+ }
}
return paths;
}
-/* check if 'foo/bar/baz.txt' matches *.txt */
static bool matchFile(const AbsolutePath & path, const string & find, bool insensitive = false){
+ return false;
+ /*
+ string file = path.path();
+ for (unsigned int index = 0; index < find.size(); index += 1){
+ if (index >= file.size()){
+ return false;
+ }
+ char find_letter = find[find.size() - index - 1];
+ char file_letter = file[file.size() - index - 1];
+ if (insensitive){
+ if (tolower(find_letter) != tolower(file_letter)){
+ return false;
+ }
+ } else {
+ if (find_letter != file_letter){
+ return false;
+ }
+ }
+ }
+
+ return true;
+ */
+}
+
+/* check if 'foo/bar/baz.txt' matches *.txt */
+static bool matchFile2(const AbsolutePath & path, const string & find, bool insensitive = false){
string file = path.getFilename().path();
+ Global::debug(0) << "Find " << find << " in " << path.path() << " insensitive? " << insensitive << std::endl;
unsigned int index = 0;
while (index < file.size()){
if (index >= find.size()){
return false;
}
if (find[index] == '*'){
return true;
}
if (insensitive){
if (tolower(find[index]) != tolower(file[index])){
return false;
}
} else {
if (find[index] != file[index]){
return false;
}
}
index += 1;
}
return true;
}
+static void testMatchFile(){
+#define test_match(check, against, insensitive) if (!matchFile(Filesystem::AbsolutePath(check), against, insensitive)){ Global::debug(0) << "Test failed, expected a match: file " << check << " find " << against << std::endl; }
+#define test_no_match(check, against, insensitive) if (matchFile(Filesystem::AbsolutePath(check), against, insensitive)){ Global::debug(0) << "Test failed, expected no match: file " << check << " find " << against << std::endl; }
+
+ test_match("foo", "foo", false);
+ test_match("fOo", "foO", true);
+ test_match("bar/foo", "foo", false);
+ test_match("bar/fOo", "foO", true);
+ test_match("bar/baz/foo.txt", "baz/foo.txt", false);
+ test_match("foobar.txt", "*.txt", false);
+ test_match("bar/foobar.txt", "*.txt", false);
+ test_no_match("fuz", "foo", false);
+ test_no_match("foo/bar.txt", "foo", false);
+ test_no_match("buz/foobar.txt", "bar/*.txt", false);
+
+#undef test_match
+#undef test_no_match
+}
+
std::vector<AbsolutePath> NetworkSystem::getFiles(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive){
vector<AbsolutePath> files = readDirectory(dataPath);
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
- if (matchFile(check, find)){
+ if (file_matches(check.getFilename().path().c_str(), find.c_str())){
paths.push_back(check);
}
}
return paths;
}
std::vector<AbsolutePath> NetworkSystem::getFilesRecursive(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive){
vector<AbsolutePath> files = readDirectory(dataPath);
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
if (matchFile(check, find)){
paths.push_back(check);
}
vector<AbsolutePath> more = getFilesRecursive(check, find, caseInsensitive);
paths.insert(paths.end(), more.begin(), more.end());
}
return paths;
}
AbsolutePath NetworkSystem::configFile(){
return AbsolutePath("paintownrc");
}
AbsolutePath NetworkSystem::userDirectory(){
return AbsolutePath("paintown-user");
}
std::vector<AbsolutePath> NetworkSystem::findDirectories(const RelativePath & path){
vector<AbsolutePath> files = readDirectory(find(path));
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
try{
/* if we can read directory contents then its a directory */
vector<AbsolutePath> more = readDirectory(check);
paths.push_back(check);
} catch (const Filesystem::NotFound & fail){
}
}
return paths;
}
AbsolutePath NetworkSystem::findInsensitive(const RelativePath & path){
try{
/* try sensitive lookup first */
return find(path);
} catch (const Filesystem::NotFound & fail){
}
/* get the base directory */
AbsolutePath directory = find(path.getDirectory());
return lookupInsensitive(directory, path.getFilename());
}
+/*
AbsolutePath NetworkSystem::lookupInsensitive(const AbsolutePath & directory, const RelativePath & path){
vector<AbsolutePath> files = readDirectory(directory);
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
if (matchFile(check, path.path(), true)){
return check;
}
}
ostringstream out;
out << "Cannot find " << path.path() << " in " << directory.path();
throw Filesystem::NotFound(__FILE__, __LINE__, out.str());
}
+*/
+
+Filesystem::AbsolutePath NetworkSystem::lookupInsensitive(const Filesystem::AbsolutePath & directory, const Filesystem::RelativePath & path){
+ if (path.path() == ""){
+ throw Filesystem::NotFound(__FILE__, __LINE__, "Given empty path to lookup");
+ }
+ if (path.path() == "."){
+ return directory;
+ }
+ if (path.path() == ".."){
+ return directory.getDirectory();
+ }
+ if (path.isFile()){
+ vector<AbsolutePath> all = getFiles(directory, "*", true);
+ for (vector<AbsolutePath>::iterator it = all.begin(); it != all.end(); it++){
+ AbsolutePath & check = *it;
+ if (InsensitivePath(check.getFilename()) == path){
+ return check;
+ }
+ }
+
+ ostringstream out;
+ out << "Cannot find " << path.path() << " in " << directory.path();
+ throw Filesystem::NotFound(__FILE__, __LINE__, out.str());
+ } else {
+ return lookupInsensitive(lookupInsensitive(directory, path.firstDirectory()), path.removeFirstDirectory());
+ }
+}
int nextFileDescriptor(){
static int next = 3;
int n = next;
next += 1;
return n;
}
int NetworkSystem::libcOpen(const char * path, int mode, int params){
Manager manager(instance, core);
Util::ReferenceCount<FileHandle> handle = manager.openFile(path);
if (handle == NULL){
return -1;
}
Util::Thread::ScopedLock scoped(lock);
int file = nextFileDescriptor();
fileTable[file] = handle;
return file;
}
ssize_t NetworkSystem::libcRead(int fd, void * buffer, size_t count){
Util::Thread::ScopedLock scoped(lock);
if (fileTable.find(fd) == fileTable.end()){
return EBADF;
}
Util::ReferenceCount<FileHandle> handle = fileTable[fd];
if (handle == NULL){
Global::debug(0) << "Handle is null!!" << std::endl;
}
return handle->read(buffer, count);
}
int NetworkSystem::libcClose(int fd){
Util::Thread::ScopedLock scoped(lock);
if (fileTable.find(fd) == fileTable.end()){
return -1;
/* set errno to EBADF */
}
fileTable.erase(fileTable.find(fd));
return 0;
}
off_t NetworkSystem::libcLseek(int fd, off_t offset, int whence){
Global::debug(2, CONTEXT) << "seek fd " << fd << " offset " << offset << " whence " << whence << std::endl;
Util::Thread::ScopedLock scoped(lock);
if (fileTable.find(fd) == fileTable.end()){
return -1;
}
Util::ReferenceCount<FileHandle> handle = fileTable[fd];
return handle->seek(offset, whence);
}
}
/* NOTE FIXME Missing I/O in Native Client */
Nacl::NetworkSystem & getSystem(){
return (Nacl::NetworkSystem&) Storage::instance();
}
extern "C" {
/* http://sourceware.org/binutils/docs-2.21/ld/Options.html#index-g_t_002d_002dwrap_003d_0040var_007bsymbol_007d-261
* --wrap=symbol
* Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to __wrap_symbol. Any undefined reference to __real_symbol will be resolved to symbol.
*/
int __wrap_open(const char * path, int mode, int params){
return getSystem().libcOpen(path, mode, params);
}
ssize_t __wrap_read(int fd, void * buf, size_t count){
return getSystem().libcRead(fd, buf, count);
}
extern int __real_close(int fd);
int __wrap_close(int fd){
/* we may be given a file descriptor that we do not own, probably
* because some file descriptors are really tied to sockets so
* if we don't own the fd then pass it to the real close function.
*/
int ok = getSystem().libcClose(fd);
if (ok == -1){
return __real_close(fd);
}
return ok;
}
off_t __wrap_lseek(int fd, off_t offset, int whence){
return getSystem().libcLseek(fd, offset, whence);
}
int pipe (int filedes[2]){
return -1;
}
int mkdir (const char *filename, mode_t mode){
return -1;
}
-int access(const char *filename, int how){
+int __wrap_access(const char *filename, int mode){
+ Global::debug(0) << "Access for " << filename << std::endl;
+ if (mode == R_OK){
+ return getSystem().exists(Filesystem::AbsolutePath(filename));
+ }
return -1;
}
char * getcwd (char *buffer, size_t size){
return NULL;
}
-int lstat (const char *path, struct stat *buf){
+int __wrap_lstat (const char *path, struct stat *buf){
+ Global::debug(0) << "Lstat for " << path << std::endl;
return -1;
}
int rmdir (const char *filename){
return -1;
}
int chdir (const char *filename){
return -1;
}
int setuid (uid_t newuid){
return 0;
}
int seteuid (uid_t uid){
return 0;
}
uid_t geteuid (void){
return NULL;
}
int setgid (gid_t gid){
return 0;
}
gid_t getgid (void){
return NULL;
}
int setegid (gid_t gid){
return 0;
}
gid_t getegid (void){
return NULL;
}
char * getlogin (void){
return NULL;
}
uid_t getuid(void){
return NULL;
}
struct passwd * getpwuid (uid_t uid){
return NULL;
}
struct passwd * getpwnam (const char *name){
return NULL;
}
struct group * getgrnam(const char *name){
return NULL;
}
struct group * getgrgid(gid_t gid){
return NULL;
}
int link (const char *oldname, const char *newname){
return -1;
}
int unlink (const char *filename){
return -1;
}
int kill(pid_t pid, int sig){
return -1;
}
}
#endif
diff --git a/util/nacl/network-system.h b/util/nacl/network-system.h
index 851c9848..0f2804a4 100644
--- a/util/nacl/network-system.h
+++ b/util/nacl/network-system.h
@@ -1,68 +1,69 @@
#ifndef _paintown_network_system_h
#define _paintown_network_system_h
#ifdef NACL
#include <map>
#include <string>
#include <vector>
#include "../file-system.h"
#include "../thread.h"
#include "../pointer.h"
namespace pp{
class Instance;
class Core;
}
namespace Nacl{
typedef Path::AbsolutePath AbsolutePath;
typedef Path::RelativePath RelativePath;
+typedef Path::InsensitivePath InsensitivePath;
class Manager;
class FileHandle;
class NetworkSystem: public Storage::System {
public:
NetworkSystem(pp::Instance * instance, pp::Core * core);
virtual ~NetworkSystem();
virtual AbsolutePath find(const RelativePath & path);
virtual RelativePath cleanse(const AbsolutePath & path);
virtual bool exists(const RelativePath & path);
virtual bool exists(const AbsolutePath & path);
virtual std::vector<AbsolutePath> getFilesRecursive(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive = false);
virtual std::vector<AbsolutePath> getFiles(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive = false);
virtual AbsolutePath configFile();
virtual AbsolutePath userDirectory();
virtual std::vector<AbsolutePath> findDirectories(const RelativePath & path);
virtual AbsolutePath findInsensitive(const RelativePath & path);
virtual AbsolutePath lookupInsensitive(const AbsolutePath & directory, const RelativePath & path);
public:
int libcOpen(const char * path, int mode, int params);
ssize_t libcRead(int fd, void * buf, size_t count);
int libcClose(int fd);
off_t libcLseek(int fd, off_t offset, int whence);
protected:
std::string readFileAsString(const AbsolutePath & path);
std::vector<AbsolutePath> readDirectory(const AbsolutePath & dataPath);
protected:
pp::Instance * instance;
pp::Core * core;
/* only one thread at a time to access the network system */
Util::Thread::LockObject lock;
// Util::ReferenceCount<Manager> manager;
std::map<AbsolutePath, bool> existsCache;
std::map<int, Util::ReferenceCount<FileHandle> > fileTable;
};
}
#endif
#endif

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:03 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68266
Default Alt Text
(48 KB)

Event Timeline