standard install dirs

This commit is contained in:
David Rose 2009-06-16 21:48:28 +00:00
parent 0c123b6bce
commit 77b6df9fd7
9 changed files with 253 additions and 39 deletions

View File

@ -35,6 +35,8 @@
#define INSTALL_HEADERS \
p3d_plugin.h
#define WIN_SYS_LIBS shell32.lib
#end lib_target
#begin bin_target

View File

@ -38,25 +38,11 @@ import zlib
import direct
from pandac.PandaModules import *
from FileSpec import FileSpec
class ArgumentError(AttributeError):
pass
class FileSpec:
def __init__(self, filename, pathname):
self.filename = filename
self.pathname = pathname
self.size = pathname.getFileSize()
self.timestamp = pathname.getTimestamp()
hv = HashVal()
hv.hashFile(pathname)
self.hash = hv.asHex()
def getParams(self):
return 'filename="%s" size=%s timestamp=%s hash="%s"' % (
self.filename, self.size, self.timestamp, self.hash)
class PackageMaker:
def __init__(self):
self.startDir = None
@ -76,10 +62,12 @@ class PackageMaker:
self.packageFullname = '%s_%s' % (
self.packageName, self.packageVersion)
self.cleanDir(self.stageDir)
self.packageStageDir = Filename(self.stageDir, '%s/%s' % (self.packageName, self.packageVersion))
self.cleanDir(self.packageStageDir)
uncompressedArchiveBasename = '%s.mf' % (self.packageFullname)
uncompressedArchivePathname = Filename(self.stageDir, uncompressedArchiveBasename)
uncompressedArchivePathname = Filename(self.packageStageDir, uncompressedArchiveBasename)
self.archive = Multifile()
if not self.archive.openWrite(uncompressedArchivePathname):
raise IOError, "Couldn't open %s for writing" % (uncompressedArchivePathname)
@ -92,7 +80,7 @@ class PackageMaker:
uncompressedArchive = FileSpec(uncompressedArchiveBasename, uncompressedArchivePathname)
compressedArchiveBasename = '%s.mf.pz' % (self.packageFullname)
compressedArchivePathname = Filename(self.stageDir, compressedArchiveBasename)
compressedArchivePathname = Filename(self.packageStageDir, compressedArchiveBasename)
print "\ncompressing"
@ -112,7 +100,7 @@ class PackageMaker:
uncompressedArchivePathname.unlink()
descFileBasename = '%s.xml' % (self.packageFullname)
descFilePathname = Filename(self.stageDir, descFileBasename)
descFilePathname = Filename(self.packageStageDir, descFileBasename)
f = open(descFilePathname.toOsSpecific(), 'w')
print >> f, '<?xml version="1.0" ?>'
@ -148,11 +136,11 @@ class PackageMaker:
localpath = ''
else:
assert dirpath.startswith(prefix)
localpath = dirpath[len(prefix):] + '/'
localpath = dirpath[len(prefix):].replace(os.sep, '/') + '/'
for basename in filenames:
file = FileSpec(localpath + basename,
Filename(self.startDir, basename))
Filename(self.startDir, localpath + basename))
print file.filename
self.components.append(file)
self.archive.addSubfile(file.filename, file.pathname, 0)

View File

@ -25,6 +25,7 @@ P3DDownload() {
_http_status_code = 0;
_total_data = 0;
_total_expected_data = 0;
_last_reported_time = 0;
_canceled = false;
_download_id = 0;
@ -126,8 +127,12 @@ receive_data(const unsigned char *this_data, size_t this_data_size) {
////////////////////////////////////////////////////////////////////
void P3DDownload::
download_progress() {
cerr << "Downloading " << get_url() << ": "
<< int(get_download_progress() * 1000.0) / 10.0 << "\n";
time_t now = time(NULL);
if (now != _last_reported_time) {
cerr << "Downloading " << get_url() << ": "
<< int(get_download_progress() * 1000.0) / 10.0 << "\n";
_last_reported_time = now;
}
}
////////////////////////////////////////////////////////////////////
@ -140,4 +145,6 @@ download_progress() {
////////////////////////////////////////////////////////////////////
void P3DDownload::
download_finished(bool success) {
cerr << "Downloading " << get_url() << ": "
<< int(get_download_progress() * 1000.0) / 10.0 << "\n";
}

View File

@ -17,6 +17,8 @@
#include "p3d_plugin_common.h"
#include <time.h>
////////////////////////////////////////////////////////////////////
// Class : P3DDownload
// Description : This represents a request to download a single file
@ -62,6 +64,7 @@ protected:
size_t _total_data;
size_t _total_expected_data;
time_t _last_reported_time;
private:
bool _canceled;

View File

@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////
#include "p3dFileDownload.h"
#include "p3dInstanceManager.h"
////////////////////////////////////////////////////////////////////
// Function: P3DFileDownload::Constructor
@ -44,6 +45,12 @@ set_filename(const string &filename) {
////////////////////////////////////////////////////////////////////
bool P3DFileDownload::
open_file() {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
if (!inst_mgr->mkfile_public(_filename)) {
cerr << "Unable to create " << _filename << "\n";
return false;
}
_file.open(_filename.c_str(), ios::out | ios::ate | ios::binary);
if (!_file) {
return false;

View File

@ -17,6 +17,10 @@
#include "p3dSession.h"
#include "p3dPackage.h"
#ifdef _WIN32
#include <shlobj.h>
#endif
P3DInstanceManager *P3DInstanceManager::_global_ptr;
////////////////////////////////////////////////////////////////////
@ -73,13 +77,21 @@ P3DInstanceManager::
////////////////////////////////////////////////////////////////////
bool P3DInstanceManager::
initialize() {
_root_dir = find_root_dir();
cerr << "_root_dir = " << _root_dir << "\n";
#ifdef _WIN32
_root_dir = "c:/cygwin/home/drose/p3ddir";
_download_url = "http://10.196.143.118/~drose/";
_download_url = "http://10.196.143.118/~drose/p3d/";
#else
_root_dir = "/Users/drose/p3ddir";
_download_url = "http://orpheus.ddrose.com/~drose/";
#endif
if (_root_dir.empty()) {
cerr << "Could not find root directory.\n";
return false;
}
return true;
}
@ -264,6 +276,67 @@ signal_request_ready() {
#endif
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::mkdir_public
// Access: Public, Static
// Description: Creates a new directory with wide-open access
// priviledges.
////////////////////////////////////////////////////////////////////
void P3DInstanceManager::
mkdir_public(const string &dirname) {
#ifdef _WIN32
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
CreateDirectory(dirname.c_str(), &sa);
#else //_WIN32
mkdir(dirname.c_str(), 0777);
#endif // _WIN32
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::mkfile_public
// Access: Public, Static
// Description: Creates a new file with wide-open access
// priviledges.
////////////////////////////////////////////////////////////////////
bool P3DInstanceManager::
mkfile_public(const string &filename) {
#ifdef _WIN32
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
HANDLE file = CreateFile(filename.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
&sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
return false;
}
CloseHandle(file);
return true;
#else // _WIN32
int fd = creat(filename.c_str(), 0777);
if (fd == -1) {
return false;
}
close(fd);
return true;
#endif // _WIN32
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_global_ptr
// Access: Public, Static
@ -292,3 +365,120 @@ create_command_instance() {
new P3DInstance(NULL, "", P3D_WT_hidden, 0, 0, 0, 0,
dummy_handle, NULL, 0);
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::find_root_dir
// Access: Private
// Description: Returns the path to the installable Panda3D directory
// on the user's machine.
////////////////////////////////////////////////////////////////////
string P3DInstanceManager::
find_root_dir() const {
#ifdef _WIN32
// Try to locate a writable directory to install Panda files into.
char buffer[MAX_PATH];
// First, check for a user-appdata Panda3D folder. If it already
// exists, use it (but don't create it yet).
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_APPDATA, true)) {
bool isdir = false;
DWORD results = GetFileAttributes(buffer);
if (results != -1) {
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (isdir) {
// The user prefix exists; do we have a Panda3D child?
string root = buffer;
root += string("/Panda3D");
// Don't attempt to create the Panda3D folder yet. Just see if
// it exists.
isdir = false;
results = GetFileAttributes(root.c_str());
if (results != -1) {
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (isdir) {
// The directory exists!
return root;
}
}
}
// If there's no user-appdata Panda3D folder, look for a common one.
// This time we'll create it if it doesn't exist, if we can. (We'd
// prefer to create the folder in a common space if we can, since
// that way it can be shared by multiple users.)
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_COMMON_APPDATA, true)) {
bool isdir = false;
DWORD results = GetFileAttributes(buffer);
if (results != -1) {
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (isdir) {
// The common prefix exists; do we have a Panda3D child?
string root = buffer;
root += string("/Panda3D");
// Attempt to make it first, if possible. Make sure the
// security attributes are wide open; this is a shared resource.
mkdir_public(root);
isdir = false;
results = GetFileAttributes(root.c_str());
if (results != -1) {
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (isdir) {
// The directory exists!
return root;
}
}
}
// Now try again to create a Panda3D folder in user-specific
// directory. Presumably we'll have write permission to this one.
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_APPDATA, true)) {
bool isdir = false;
DWORD results = GetFileAttributes(buffer);
if (results != -1) {
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (isdir) {
// The user prefix exists; do we have a Panda3D child?
string root = buffer;
root += string("/Panda3D");
// Attempt to make it first, if possible. This time we don't
// attempt to make it public, since this is a private space.
CreateDirectory(root.c_str(), NULL);
isdir = false;
results = GetFileAttributes(root.c_str());
if (results != -1) {
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (isdir) {
// The directory exists!
return root;
}
}
}
// Couldn't find a directory. Bail.
cerr << "Couldn't find a root directory.\n";
return string();
#else // _WIN32
return "/Users/drose/p3ddir";
#endif
}

View File

@ -64,10 +64,14 @@ public:
int get_unique_session_index();
void signal_request_ready();
static void mkdir_public(const string &dirname);
static bool mkfile_public(const string &dirname);
static P3DInstanceManager *get_global_ptr();
private:
void create_command_instance();
string find_root_dir() const;
private:
string _root_dir;

View File

@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////
#include "p3dMultifileReader.h"
#include "p3dInstanceManager.h"
// This sequence of bytes begins each Multifile to identify it as a
// Multifile.
@ -77,6 +78,8 @@ extract(const string &pathname, const string &to_dir) {
return false;
}
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
// Now walk through all of the files.
Subfiles::iterator si;
for (si = _subfiles.begin(); si != _subfiles.end(); ++si) {
@ -84,12 +87,17 @@ extract(const string &pathname, const string &to_dir) {
cerr << s._filename << "\n";
string output_pathname = to_dir + "/" + s._filename;
ofstream out(output_pathname.c_str(), ios::out | ios::trunc | ios::binary);
if (!out) {
if (!inst_mgr->mkfile_public(output_pathname)) {
cerr << "Unable to create " << output_pathname << "\n";
return false;
}
ofstream out(output_pathname.c_str(), ios::out | ios::binary);
if (!out) {
cerr << "Unable to write to " << output_pathname << "\n";
return false;
}
_in.seekg(s._start);
static const size_t buffer_size = 1024;

View File

@ -58,18 +58,10 @@ P3DPackage(const string &package_name, const string &package_version) :
// Ensure the package directory exists; create it if it does not.
_package_dir = inst_mgr->get_root_dir() + string("/") + _package_name;
#ifdef _WIN32
_mkdir(_package_dir.c_str());
#else
mkdir(_package_dir.c_str(), 0777);
#endif
inst_mgr->mkdir_public(_package_dir);
_package_dir += string("/") + _package_version;
#ifdef _WIN32
_mkdir(_package_dir.c_str());
#else
mkdir(_package_dir.c_str(), 0777);
#endif
inst_mgr->mkdir_public(_package_dir);
_desc_file_basename = _package_fullname + ".xml";
_desc_file_pathname = _package_dir + "/" + _desc_file_basename;
@ -77,6 +69,9 @@ P3DPackage(const string &package_name, const string &package_version) :
// TODO: we should check the desc file for updates with the server.
// Perhaps this should be done in a parent class.
// TODO: if the desc file exists, and is consistent with the server
// contents file, don't re-download it.
/*
// Load the desc file, if it exists.
TiXmlDocument doc(_desc_file_pathname.c_str());
if (!doc.LoadFile()) {
@ -84,6 +79,9 @@ P3DPackage(const string &package_name, const string &package_version) :
} else {
got_desc_file(&doc, false);
}
*/
download_desc_file();
}
////////////////////////////////////////////////////////////////////
@ -312,6 +310,13 @@ uncompress_archive() {
return;
}
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
if (!inst_mgr->mkfile_public(target_pathname)) {
cerr << "Unable to create " << target_pathname << "\n";
report_done(false);
return;
}
ofstream target(target_pathname.c_str(), ios::out | ios::binary);
if (!target) {
cerr << "Couldn't write to " << target_pathname << "\n";