Applied patch by sil2100 that enables handling of script files (bug #3762)
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36020 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,6 +11,7 @@ Application PackageInstaller :
|
|||||||
PackageView.cpp
|
PackageView.cpp
|
||||||
PackageInfo.cpp
|
PackageInfo.cpp
|
||||||
PackageItem.cpp
|
PackageItem.cpp
|
||||||
|
PackageInstall.cpp
|
||||||
PackageStatus.cpp
|
PackageStatus.cpp
|
||||||
PackageTextViewer.cpp
|
PackageTextViewer.cpp
|
||||||
PackageImageViewer.cpp
|
PackageImageViewer.cpp
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ enum {
|
|||||||
P_NONE = 0,
|
P_NONE = 0,
|
||||||
P_FILE,
|
P_FILE,
|
||||||
P_DIRECTORY,
|
P_DIRECTORY,
|
||||||
P_LINK
|
P_LINK,
|
||||||
|
P_SCRIPT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -86,6 +87,14 @@ PackageInfo::~PackageInfo()
|
|||||||
delete file;
|
delete file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
file = static_cast<PackageScript *>(fScripts.RemoveItem((long int)0));
|
||||||
|
if (file == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
delete file;
|
||||||
|
}
|
||||||
|
|
||||||
delete fPackageFile;
|
delete fPackageFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,63 +633,31 @@ PackageInfo::Parse()
|
|||||||
RETURN_AND_SET_STATUS(B_ERROR);
|
RETURN_AND_SET_STATUS(B_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Here's the deal... there seems to be a strange ScrI tag that
|
#define INIT_VARS(tag, type) \
|
||||||
// seems to mean script files (check this). It seems exaclty the same
|
parser_debug(tag "\n"); \
|
||||||
// as a normal file (just as script files are normal files) so for
|
element = type; \
|
||||||
// now I'm treating those as files. Check if it's correct!
|
mimeString = ""; \
|
||||||
// No, it isn't and I will fix this soon.
|
nameString = ""; \
|
||||||
if (!memcmp(buffer, "FilI", 5) || !memcmp(buffer, "ScrI", 5)) {
|
linkString = ""; \
|
||||||
parser_debug("FilI\n");
|
signatureString = ""; \
|
||||||
element = P_FILE;
|
itemGroups = 0; \
|
||||||
|
ctime = 0; \
|
||||||
|
mtime = 0; \
|
||||||
|
offset = 0; \
|
||||||
|
cust = 0; \
|
||||||
|
mode = 0; \
|
||||||
|
platform = 0xffffffff; \
|
||||||
|
size = 0; \
|
||||||
|
originalSize = 0
|
||||||
|
|
||||||
mimeString = "";
|
if (!memcmp(buffer, "FilI", 5)) {
|
||||||
nameString = "";
|
INIT_VARS("FilI", P_FILE);
|
||||||
signatureString = "";
|
|
||||||
|
|
||||||
itemGroups = 0;
|
|
||||||
ctime = 0;
|
|
||||||
mtime = 0;
|
|
||||||
offset = 0;
|
|
||||||
itemGroups = 0;
|
|
||||||
cust = 0;
|
|
||||||
mode = 0;
|
|
||||||
platform = 0xffffffff;
|
|
||||||
|
|
||||||
size = 0;
|
|
||||||
originalSize = 0;
|
|
||||||
} else if (!memcmp(buffer, "FldI", 5)) {
|
} else if (!memcmp(buffer, "FldI", 5)) {
|
||||||
parser_debug("FldI\n");
|
INIT_VARS("FldI", P_DIRECTORY);
|
||||||
element = P_DIRECTORY;
|
|
||||||
|
|
||||||
nameString = "";
|
|
||||||
|
|
||||||
itemGroups = 0;
|
|
||||||
ctime = 0;
|
|
||||||
mtime = 0;
|
|
||||||
offset = 0;
|
|
||||||
itemGroups = 0;
|
|
||||||
cust = 0;
|
|
||||||
platform = 0xffffffff;
|
|
||||||
|
|
||||||
size = 0;
|
|
||||||
originalSize = 0;
|
|
||||||
} else if (!memcmp(buffer, "LnkI", 5)) {
|
} else if (!memcmp(buffer, "LnkI", 5)) {
|
||||||
parser_debug("LnkI\n");
|
INIT_VARS("LnkI", P_LINK);
|
||||||
element = P_LINK;
|
} else if (!memcmp(buffer, "ScrI", 5)) {
|
||||||
|
INIT_VARS("ScrI", P_SCRIPT);
|
||||||
nameString = "";
|
|
||||||
linkString = "";
|
|
||||||
|
|
||||||
itemGroups = 0;
|
|
||||||
ctime = 0;
|
|
||||||
mtime = 0;
|
|
||||||
offset = 0;
|
|
||||||
itemGroups = 0;
|
|
||||||
cust = 0;
|
|
||||||
platform = 0xffffffff;
|
|
||||||
|
|
||||||
size = 0;
|
|
||||||
originalSize = 0;
|
|
||||||
} else if (!memcmp(buffer, "Name", 5)) {
|
} else if (!memcmp(buffer, "Name", 5)) {
|
||||||
if (element == P_NONE) {
|
if (element == P_NONE) {
|
||||||
RETURN_AND_SET_STATUS(B_ERROR);
|
RETURN_AND_SET_STATUS(B_ERROR);
|
||||||
@@ -795,7 +772,7 @@ PackageInfo::Parse()
|
|||||||
swap_data(B_UINT64_TYPE, &size, sizeof(uint64),
|
swap_data(B_UINT64_TYPE, &size, sizeof(uint64),
|
||||||
B_SWAP_BENDIAN_TO_HOST);
|
B_SWAP_BENDIAN_TO_HOST);
|
||||||
} else if (!memcmp(buffer, "OrgS", 5)) {
|
} else if (!memcmp(buffer, "OrgS", 5)) {
|
||||||
if (element != P_FILE && element != P_LINK) {
|
if (element != P_FILE && element != P_LINK && element != P_SCRIPT) {
|
||||||
RETURN_AND_SET_STATUS(B_ERROR);
|
RETURN_AND_SET_STATUS(B_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,6 +996,9 @@ PackageInfo::Parse()
|
|||||||
item = new PackageLink(fPackageFile, dest, linkString,
|
item = new PackageLink(fPackageFile, dest, linkString,
|
||||||
localType, ctime, mtime, mode, offset, size);
|
localType, ctime, mtime, mode, offset, size);
|
||||||
}
|
}
|
||||||
|
} else if (element == P_SCRIPT) {
|
||||||
|
fScripts.AddItem(new PackageScript(fPackageFile, offset, size,
|
||||||
|
originalSize));
|
||||||
} else {
|
} else {
|
||||||
// If the directory tree count is equal to zero, this means all
|
// If the directory tree count is equal to zero, this means all
|
||||||
// directory trees have been closed and a padding sequence means the
|
// directory trees have been closed and a padding sequence means the
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ class PackageInfo {
|
|||||||
const char *GetDisclaimer() { return fDisclaimer.String(); }
|
const char *GetDisclaimer() { return fDisclaimer.String(); }
|
||||||
BMallocIO *GetSplashScreen() { return fHasImage ? &fImage : NULL; }
|
BMallocIO *GetSplashScreen() { return fHasImage ? &fImage : NULL; }
|
||||||
int32 GetProfileCount() { return fProfiles.CountItems(); }
|
int32 GetProfileCount() { return fProfiles.CountItems(); }
|
||||||
pkg_profile *GetProfile(int32 num) { return static_cast<pkg_profile *>(fProfiles.ItemAt(num)); }
|
pkg_profile *GetProfile(int32 num) {
|
||||||
|
return static_cast<pkg_profile *>(fProfiles.ItemAt(num)); }
|
||||||
|
int32 GetScriptCount() { return fScripts.CountItems(); }
|
||||||
|
PackageScript *GetScript(int32 num) {
|
||||||
|
return static_cast<PackageScript *>(fScripts.ItemAt(num)); }
|
||||||
|
|
||||||
status_t Parse();
|
status_t Parse();
|
||||||
status_t InitCheck() { return fStatus; }
|
status_t InitCheck() { return fStatus; }
|
||||||
@@ -56,6 +60,7 @@ class PackageInfo {
|
|||||||
bool fHasImage;
|
bool fHasImage;
|
||||||
|
|
||||||
BList fFiles; // Holds all files in the package
|
BList fFiles; // Holds all files in the package
|
||||||
|
BList fScripts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <fs_info.h>
|
#include <fs_info.h>
|
||||||
#include <NodeInfo.h>
|
#include <NodeInfo.h>
|
||||||
|
#include <OS.h>
|
||||||
#include <SymLink.h>
|
#include <SymLink.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
|
|
||||||
@@ -37,10 +38,14 @@ enum {
|
|||||||
P_ATTRIBUTE
|
P_ATTRIBUTE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const char **environ;
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize)
|
inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize)
|
||||||
{
|
{
|
||||||
|
parser_debug("inflate_data() called - input_size: %ld, output_size: %ld\n",
|
||||||
|
inSize, outSize);
|
||||||
z_stream stream;
|
z_stream stream;
|
||||||
stream.zalloc = Z_NULL;
|
stream.zalloc = Z_NULL;
|
||||||
stream.zfree = Z_NULL;
|
stream.zfree = Z_NULL;
|
||||||
@@ -374,6 +379,68 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageItem::SkipAttribute(uint8 *buffer, bool *attrStarted, bool *done)
|
||||||
|
{
|
||||||
|
status_t ret = B_OK;
|
||||||
|
uint32 length;
|
||||||
|
|
||||||
|
if (!memcmp(buffer, "BeAI", 5)) {
|
||||||
|
parser_debug(" Attribute started.\n");
|
||||||
|
*attrStarted = true;
|
||||||
|
} else if (!memcmp(buffer, "BeAN", 5)) {
|
||||||
|
if (!*attrStarted) {
|
||||||
|
ret = B_ERROR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_debug(" BeAN.\n");
|
||||||
|
fPackage->Read(&length, 4);
|
||||||
|
swap_data(B_UINT32_TYPE, &length, sizeof(uint32),
|
||||||
|
B_SWAP_BENDIAN_TO_HOST);
|
||||||
|
|
||||||
|
fPackage->Seek(length, SEEK_CUR);
|
||||||
|
} else if (!memcmp(buffer, "BeAT", 5)) {
|
||||||
|
if (!*attrStarted) {
|
||||||
|
ret = B_ERROR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_debug(" BeAT.\n");
|
||||||
|
fPackage->Seek(4, SEEK_CUR);
|
||||||
|
} else if (!memcmp(buffer, "BeAD", 5)) {
|
||||||
|
if (!*attrStarted) {
|
||||||
|
ret = B_ERROR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_debug(" BeAD.\n");
|
||||||
|
uint64 length64;
|
||||||
|
fPackage->Read(&length64, 8);
|
||||||
|
swap_data(B_UINT64_TYPE, &length64, sizeof(length64),
|
||||||
|
B_SWAP_BENDIAN_TO_HOST);
|
||||||
|
|
||||||
|
fPackage->Seek(12 + length64, SEEK_CUR);
|
||||||
|
|
||||||
|
parser_debug(" Data skipped successfuly.\n");
|
||||||
|
} else if (!memcmp(buffer, padding, 7)) {
|
||||||
|
if (!*attrStarted) {
|
||||||
|
*done = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_debug(" Padding.\n");
|
||||||
|
*attrStarted = false;
|
||||||
|
parser_debug(" > Attribute skipped.\n");
|
||||||
|
} else {
|
||||||
|
parser_debug(" Unknown attribute\n");
|
||||||
|
ret = B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
|
PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
|
||||||
bool *done)
|
bool *done)
|
||||||
@@ -425,6 +492,203 @@ PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageScript
|
||||||
|
|
||||||
|
|
||||||
|
PackageScript::PackageScript(BFile *parent, uint64 offset, uint64 size,
|
||||||
|
uint64 originalSize)
|
||||||
|
:
|
||||||
|
PackageItem(parent, NULL, 0, 0, 0, offset, size),
|
||||||
|
fOriginalSize(originalSize),
|
||||||
|
fThreadId(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageScript::DoInstall(const char *path, ItemState *state)
|
||||||
|
{
|
||||||
|
status_t ret = B_OK;
|
||||||
|
parser_debug("Script: DoInstall() called!\n");
|
||||||
|
|
||||||
|
if (fOffset) {
|
||||||
|
parser_debug("We have an offset\n");
|
||||||
|
if (!fPackage)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
ret = fPackage->InitCheck();
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// We need to parse the data section now
|
||||||
|
fPackage->Seek(fOffset, SEEK_SET);
|
||||||
|
uint8 buffer[7];
|
||||||
|
bool attrStarted = false, done = false;
|
||||||
|
|
||||||
|
uint8 section = P_ATTRIBUTE;
|
||||||
|
|
||||||
|
while (fPackage->Read(buffer, 7) == 7) {
|
||||||
|
if (!memcmp(buffer, "FBeA", 5)) {
|
||||||
|
parser_debug("-> Attribute\n");
|
||||||
|
section = P_ATTRIBUTE;
|
||||||
|
continue;
|
||||||
|
} else if (!memcmp(buffer, "FiDa", 5)) {
|
||||||
|
parser_debug("-> File data\n");
|
||||||
|
section = P_DATA;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (section) {
|
||||||
|
case P_ATTRIBUTE:
|
||||||
|
ret = SkipAttribute(buffer, &attrStarted, &done);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case P_DATA:
|
||||||
|
ret = _ParseScript(buffer, fOriginalSize, &done);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != B_OK || done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_debug("Ret: %d %s\n", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
PackageScript::ItemKind()
|
||||||
|
{
|
||||||
|
return "script";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageScript::_ParseScript(uint8 *buffer, uint64 originalSize, bool *done)
|
||||||
|
{
|
||||||
|
status_t ret = B_OK;
|
||||||
|
|
||||||
|
if (!memcmp(buffer, "FiMF", 5)) {
|
||||||
|
parser_debug(" Found file (script) data.\n");
|
||||||
|
uint64 compressed, original;
|
||||||
|
fPackage->Read(&compressed, 8);
|
||||||
|
swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64),
|
||||||
|
B_SWAP_BENDIAN_TO_HOST);
|
||||||
|
|
||||||
|
fPackage->Read(&original, 8);
|
||||||
|
swap_data(B_UINT64_TYPE, &original, sizeof(uint64),
|
||||||
|
B_SWAP_BENDIAN_TO_HOST);
|
||||||
|
parser_debug(" Still good... (%llu : %llu)\n", original,
|
||||||
|
originalSize);
|
||||||
|
|
||||||
|
if (original != originalSize) {
|
||||||
|
parser_debug(" File size mismatch\n");
|
||||||
|
return B_ERROR; // File size mismatch
|
||||||
|
}
|
||||||
|
parser_debug(" Still good...\n");
|
||||||
|
|
||||||
|
if (fPackage->Read(buffer, 4) != 4) {
|
||||||
|
parser_debug(" Read(buffer, 4) failed\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
parser_debug(" Still good...\n");
|
||||||
|
|
||||||
|
uint8 *temp = new uint8[compressed];
|
||||||
|
if (fPackage->Read(temp, compressed) != (int64)compressed) {
|
||||||
|
parser_debug(" Read(temp, compressed) failed\n");
|
||||||
|
delete[] temp;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 *script = new uint8[original];
|
||||||
|
ret = inflate_data(temp, compressed, script, original);
|
||||||
|
if (ret != B_OK) {
|
||||||
|
parser_debug(" inflate_data failed\n");
|
||||||
|
delete[] temp;
|
||||||
|
delete[] script;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _RunScript(script, originalSize);
|
||||||
|
delete[] script;
|
||||||
|
delete[] temp;
|
||||||
|
parser_debug(" Script data inflation complete!\n");
|
||||||
|
} else if (!memcmp(buffer, padding, 7)) {
|
||||||
|
*done = true;
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
parser_debug("_ParseData unknown tag\n");
|
||||||
|
ret = B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageScript::_RunScript(uint8 *script, uint32 len)
|
||||||
|
{
|
||||||
|
// This function written by Peter Folk <[email protected]>
|
||||||
|
// and published in the BeDevTalk FAQ, modified for use in the
|
||||||
|
// PackageInstaller
|
||||||
|
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
|
||||||
|
|
||||||
|
// Save current FDs
|
||||||
|
int old_in = dup(0);
|
||||||
|
int old_out = dup(1);
|
||||||
|
int old_err = dup(2);
|
||||||
|
|
||||||
|
int filedes[2];
|
||||||
|
|
||||||
|
/* Create new pipe FDs as stdin, stdout, stderr */
|
||||||
|
pipe(filedes); dup2(filedes[0], 0); close(filedes[0]);
|
||||||
|
int in = filedes[1]; // Write to in, appears on cmd's stdin
|
||||||
|
pipe(filedes); dup2(filedes[1], 1); close(filedes[1]);
|
||||||
|
pipe(filedes); dup2(filedes[1], 2); close(filedes[1]);
|
||||||
|
|
||||||
|
const char **argv = new const char * [3];
|
||||||
|
argv[0] = strdup("/bin/sh");
|
||||||
|
argv[1] = strdup("-s");
|
||||||
|
argv[2] = NULL;
|
||||||
|
|
||||||
|
// "load" command.
|
||||||
|
fThreadId = load_image(2, argv, environ);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
delete argv[i];
|
||||||
|
delete [] argv;
|
||||||
|
|
||||||
|
if (fThreadId < B_OK)
|
||||||
|
return fThreadId;
|
||||||
|
|
||||||
|
// thread id is now suspended.
|
||||||
|
setpgid(fThreadId, fThreadId);
|
||||||
|
|
||||||
|
// Restore old FDs
|
||||||
|
close(0); dup(old_in); close(old_in);
|
||||||
|
close(1); dup(old_out); close(old_out);
|
||||||
|
close(2); dup(old_err); close(old_err);
|
||||||
|
|
||||||
|
set_thread_priority(fThreadId, B_LOW_PRIORITY);
|
||||||
|
resume_thread(fThreadId);
|
||||||
|
|
||||||
|
// Write the script
|
||||||
|
if (write(in, script, len) != (int32)len || write(in, "\nexit\n", 6) != 6) {
|
||||||
|
parser_debug("Writing script failed\n");
|
||||||
|
kill_thread(fThreadId);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PackageDirectory
|
// #pragma mark - PackageDirectory
|
||||||
|
|
||||||
|
|
||||||
@@ -437,11 +701,11 @@ PackageDirectory::PackageDirectory(BFile *parent, const BString &path,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageDirectory::WriteToPath(const char *path, ItemState *state)
|
PackageDirectory::DoInstall(const char *path, ItemState *state)
|
||||||
{
|
{
|
||||||
BPath &destination = state->destination;
|
BPath &destination = state->destination;
|
||||||
status_t ret;
|
status_t ret;
|
||||||
parser_debug("Directory: %s WriteToPath() called!\n", fPath.String());
|
parser_debug("Directory: %s DoInstall() called!\n", fPath.String());
|
||||||
|
|
||||||
ret = InitPath(path, &destination);
|
ret = InitPath(path, &destination);
|
||||||
parser_debug("Ret: %d %s\n", ret, strerror(ret));
|
parser_debug("Ret: %d %s\n", ret, strerror(ret));
|
||||||
@@ -499,14 +763,14 @@ PackageFile::PackageFile(BFile *parent, const BString &path, uint8 type,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageFile::WriteToPath(const char *path, ItemState *state)
|
PackageFile::DoInstall(const char *path, ItemState *state)
|
||||||
{
|
{
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BPath &destination = state->destination;
|
BPath &destination = state->destination;
|
||||||
status_t ret = B_OK;
|
status_t ret = B_OK;
|
||||||
parser_debug("File: %s WriteToPath() called!\n", fPath.String());
|
parser_debug("File: %s DoInstall() called!\n", fPath.String());
|
||||||
|
|
||||||
BFile file;
|
BFile file;
|
||||||
if (state->status == B_NO_INIT || destination.InitCheck() != B_OK) {
|
if (state->status == B_NO_INIT || destination.InitCheck() != B_OK) {
|
||||||
@@ -661,14 +925,14 @@ PackageLink::PackageLink(BFile *parent, const BString &path,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageLink::WriteToPath(const char *path, ItemState *state)
|
PackageLink::DoInstall(const char *path, ItemState *state)
|
||||||
{
|
{
|
||||||
if (state == NULL)
|
if (state == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
status_t ret = B_OK;
|
status_t ret = B_OK;
|
||||||
BSymLink symlink;
|
BSymLink symlink;
|
||||||
parser_debug("Symlink: %s WriteToPath() called!\n", fPath.String());
|
parser_debug("Symlink: %s DoInstall() called!\n", fPath.String());
|
||||||
|
|
||||||
BPath &destination = state->destination;
|
BPath &destination = state->destination;
|
||||||
BDirectory *dir = &state->parent;
|
BDirectory *dir = &state->parent;
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ public:
|
|||||||
uint64 offset = 0, uint64 size = 0);
|
uint64 offset = 0, uint64 size = 0);
|
||||||
virtual ~PackageItem();
|
virtual ~PackageItem();
|
||||||
|
|
||||||
virtual status_t WriteToPath(const char* path = NULL,
|
virtual status_t DoInstall(const char* path = NULL,
|
||||||
ItemState *state = NULL) = 0;
|
ItemState *state = NULL) = 0;
|
||||||
virtual void SetTo(BFile* parent, const BString& path,
|
virtual void SetTo(BFile* parent, const BString& path,
|
||||||
uint8 type, uint32 ctime, uint32 mtime,
|
uint8 type, uint32 ctime, uint32 mtime,
|
||||||
uint64 offset = 0, uint64 size = 0);
|
uint64 offset = 0, uint64 size = 0);
|
||||||
virtual const char* ItemKind() = 0;
|
virtual const char* ItemKind() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
status_t InitPath(const char* path, BPath* destination);
|
status_t InitPath(const char* path, BPath* destination);
|
||||||
status_t HandleAttributes(BPath* destination, BNode* node,
|
status_t HandleAttributes(BPath* destination, BNode* node,
|
||||||
const char* header);
|
const char* header);
|
||||||
@@ -91,6 +91,8 @@ protected:
|
|||||||
uint64* tempSize, uint64* attrCSize,
|
uint64* tempSize, uint64* attrCSize,
|
||||||
uint64* attrOSize, bool* attrStarted,
|
uint64* attrOSize, bool* attrStarted,
|
||||||
bool* done);
|
bool* done);
|
||||||
|
status_t SkipAttribute(uint8 *buffer, bool *attrStarted,
|
||||||
|
bool *done);
|
||||||
status_t ParseData(uint8* buffer, BFile* file,
|
status_t ParseData(uint8* buffer, BFile* file,
|
||||||
uint64 originalSize, bool* done);
|
uint64 originalSize, bool* done);
|
||||||
|
|
||||||
@@ -111,12 +113,34 @@ public:
|
|||||||
uint8 type, uint32 ctime, uint32 mtime,
|
uint8 type, uint32 ctime, uint32 mtime,
|
||||||
uint64 offset = 0, uint64 size = 0);
|
uint64 offset = 0, uint64 size = 0);
|
||||||
|
|
||||||
virtual status_t WriteToPath(const char* path = NULL,
|
virtual status_t DoInstall(const char* path = NULL,
|
||||||
ItemState *state = NULL);
|
ItemState *state = NULL);
|
||||||
virtual const char* ItemKind();
|
virtual const char* ItemKind();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PackageScript : public PackageItem {
|
||||||
|
public:
|
||||||
|
PackageScript(BFile* parent, uint64 offset = 0,
|
||||||
|
uint64 size = 0, uint64 originalSize = 0);
|
||||||
|
|
||||||
|
virtual status_t DoInstall(const char* path = NULL,
|
||||||
|
ItemState *state = NULL);
|
||||||
|
virtual const char* ItemKind();
|
||||||
|
|
||||||
|
thread_id GetThreadId() { return fThreadId; }
|
||||||
|
void SetThreadId(thread_id id) { fThreadId = id; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _ParseScript(uint8 *buffer, uint64 originalSize,
|
||||||
|
bool *done);
|
||||||
|
status_t _RunScript(uint8 *script, uint32 len);
|
||||||
|
|
||||||
|
uint64 fOriginalSize;
|
||||||
|
thread_id fThreadId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class PackageFile : public PackageItem {
|
class PackageFile : public PackageItem {
|
||||||
public:
|
public:
|
||||||
PackageFile(BFile* parent, const BString& path,
|
PackageFile(BFile* parent, const BString& path,
|
||||||
@@ -125,7 +149,7 @@ public:
|
|||||||
uint32 platform, const BString& mime,
|
uint32 platform, const BString& mime,
|
||||||
const BString& signature, uint32 mode);
|
const BString& signature, uint32 mode);
|
||||||
|
|
||||||
virtual status_t WriteToPath(const char* path = NULL,
|
virtual status_t DoInstall(const char* path = NULL,
|
||||||
ItemState *state = NULL);
|
ItemState *state = NULL);
|
||||||
virtual const char* ItemKind();
|
virtual const char* ItemKind();
|
||||||
|
|
||||||
@@ -146,7 +170,7 @@ public:
|
|||||||
uint32 mtime, uint32 mode, uint64 offset = 0,
|
uint32 mtime, uint32 mode, uint64 offset = 0,
|
||||||
uint64 size = 0);
|
uint64 size = 0);
|
||||||
|
|
||||||
virtual status_t WriteToPath(const char* path = NULL,
|
virtual status_t DoInstall(const char* path = NULL,
|
||||||
ItemState *state = NULL);
|
ItemState *state = NULL);
|
||||||
virtual const char* ItemKind();
|
virtual const char* ItemKind();
|
||||||
|
|
||||||
|
|||||||
@@ -92,10 +92,11 @@ StopButton::Draw(BRect updateRect)
|
|||||||
|
|
||||||
|
|
||||||
PackageStatus::PackageStatus(const char *title, const char *label,
|
PackageStatus::PackageStatus(const char *title, const char *label,
|
||||||
const char *trailing)
|
const char *trailing, BHandler *parent)
|
||||||
: BWindow(BRect(200, 200, 550, 255), title, B_TITLED_WINDOW,
|
: BWindow(BRect(200, 200, 550, 255), title, B_TITLED_WINDOW,
|
||||||
B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE, 0),
|
B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE, 0),
|
||||||
fIsStopped(false)
|
fIsStopped(false),
|
||||||
|
fParent(parent)
|
||||||
{
|
{
|
||||||
SetLayout(new BGroupLayout(B_VERTICAL));
|
SetLayout(new BGroupLayout(B_VERTICAL));
|
||||||
|
|
||||||
@@ -129,6 +130,13 @@ PackageStatus::MessageReceived(BMessage *msg)
|
|||||||
switch (msg->what) {
|
switch (msg->what) {
|
||||||
case P_MSG_STOP:
|
case P_MSG_STOP:
|
||||||
fIsStopped = true;
|
fIsStopped = true;
|
||||||
|
if (fParent != NULL) {
|
||||||
|
// If we have a parent defined, forward this message
|
||||||
|
BLooper *loop = fParent->Looper();
|
||||||
|
if (loop != NULL) {
|
||||||
|
loop->PostMessage(msg, fParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BWindow::MessageReceived(msg);
|
BWindow::MessageReceived(msg);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class StopButton : public BButton {
|
|||||||
class PackageStatus : public BWindow {
|
class PackageStatus : public BWindow {
|
||||||
public:
|
public:
|
||||||
PackageStatus(const char *title, const char *label = NULL,
|
PackageStatus(const char *title, const char *label = NULL,
|
||||||
const char *trailing = NULL);
|
const char *trailing = NULL, BHandler *parent = NULL);
|
||||||
~PackageStatus();
|
~PackageStatus();
|
||||||
|
|
||||||
void MessageReceived(BMessage *msg);
|
void MessageReceived(BMessage *msg);
|
||||||
@@ -46,6 +46,7 @@ class PackageStatus : public BWindow {
|
|||||||
BStatusBar *fStatus;
|
BStatusBar *fStatus;
|
||||||
StopButton *fButton;
|
StopButton *fButton;
|
||||||
bool fIsStopped;
|
bool fIsStopped;
|
||||||
|
BHandler *fParent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ PackageView::PackageView(BRect frame, const entry_ref *ref)
|
|||||||
//BView("package_view", B_WILL_DRAW, new BGroupLayout(B_HORIZONTAL)),
|
//BView("package_view", B_WILL_DRAW, new BGroupLayout(B_HORIZONTAL)),
|
||||||
fOpenPanel(new BFilePanel(B_OPEN_PANEL, NULL, NULL,
|
fOpenPanel(new BFilePanel(B_OPEN_PANEL, NULL, NULL,
|
||||||
B_DIRECTORY_NODE, false)),
|
B_DIRECTORY_NODE, false)),
|
||||||
fInfo(ref)
|
fInfo(ref),
|
||||||
|
fInstallProcess(this)
|
||||||
{
|
{
|
||||||
_InitView();
|
_InitView();
|
||||||
|
|
||||||
@@ -121,7 +122,8 @@ PackageView::AttachedToWindow()
|
|||||||
// attaching the view to the window
|
// attaching the view to the window
|
||||||
_GroupChanged(0);
|
_GroupChanged(0);
|
||||||
|
|
||||||
fStatusWindow = new PackageStatus(T("Installation progress"));
|
fStatusWindow = new PackageStatus(T("Installation progress"), NULL, NULL,
|
||||||
|
this);
|
||||||
|
|
||||||
// Show the splash screen, if present
|
// Show the splash screen, if present
|
||||||
BMallocIO *image = fInfo.GetSplashScreen();
|
BMallocIO *image = fInfo.GetSplashScreen();
|
||||||
@@ -133,10 +135,10 @@ PackageView::AttachedToWindow()
|
|||||||
// Show the disclaimer/info text popup, if present
|
// Show the disclaimer/info text popup, if present
|
||||||
BString disclaimer = fInfo.GetDisclaimer();
|
BString disclaimer = fInfo.GetDisclaimer();
|
||||||
if (disclaimer.Length() != 0) {
|
if (disclaimer.Length() != 0) {
|
||||||
PackageTextViewer *text = new PackageTextViewer(disclaimer.String());
|
PackageTextViewer *text = new PackageTextViewer(disclaimer.String());
|
||||||
int32 selection = text->Go();
|
int32 selection = text->Go();
|
||||||
// The user didn't accept our disclaimer, this means we cannot continue.
|
// The user didn't accept our disclaimer, this means we cannot continue.
|
||||||
if (selection == 0) {
|
if (selection == 0) {
|
||||||
BWindow *parent = Window();
|
BWindow *parent = Window();
|
||||||
if (parent && parent->Lock())
|
if (parent && parent->Lock())
|
||||||
parent->Quit();
|
parent->Quit();
|
||||||
@@ -153,36 +155,11 @@ PackageView::MessageReceived(BMessage *msg)
|
|||||||
case P_MSG_INSTALL:
|
case P_MSG_INSTALL:
|
||||||
{
|
{
|
||||||
fInstall->SetEnabled(false);
|
fInstall->SetEnabled(false);
|
||||||
|
fInstallTypes->SetEnabled(false);
|
||||||
|
fDestination->SetEnabled(false);
|
||||||
fStatusWindow->Show();
|
fStatusWindow->Show();
|
||||||
BAlert *notify;
|
|
||||||
status_t ret = Install();
|
|
||||||
if (ret == B_OK) {
|
|
||||||
notify = new BAlert("installation_success",
|
|
||||||
T("The package you requested has been successfully installed "
|
|
||||||
"on your system."), T("OK"));
|
|
||||||
|
|
||||||
notify->Go();
|
|
||||||
fStatusWindow->Hide();
|
|
||||||
|
|
||||||
BWindow *parent = Window();
|
|
||||||
if (parent && parent->Lock())
|
|
||||||
parent->Quit();
|
|
||||||
}
|
|
||||||
else if (ret == B_FILE_EXISTS)
|
|
||||||
notify = new BAlert("installation_aborted",
|
|
||||||
T("The installation of the package has been aborted."), T("OK"));
|
|
||||||
else {
|
|
||||||
notify = new BAlert("installation_failed", // TODO: Review this
|
|
||||||
T("The requested package failed to install on your system. This "
|
|
||||||
"might be a problem with the target package file. Please consult "
|
|
||||||
"this issue with the package distributor."), T("OK"), NULL,
|
|
||||||
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
|
||||||
fprintf(stderr, "Error while installing the package : %s\n", strerror(ret));
|
|
||||||
}
|
|
||||||
notify->Go();
|
|
||||||
fStatusWindow->Hide();
|
|
||||||
fInstall->SetEnabled(true);
|
|
||||||
|
|
||||||
|
fInstallProcess.Start();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case P_MSG_PATH_CHANGED:
|
case P_MSG_PATH_CHANGED:
|
||||||
@@ -204,6 +181,65 @@ PackageView::MessageReceived(BMessage *msg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case P_MSG_I_FINISHED:
|
||||||
|
{
|
||||||
|
BAlert *notify = new BAlert("installation_success",
|
||||||
|
T("The package you requested has been successfully installed "
|
||||||
|
"on your system."), T("OK"));
|
||||||
|
|
||||||
|
notify->Go();
|
||||||
|
fStatusWindow->Hide();
|
||||||
|
fInstall->SetEnabled(true);
|
||||||
|
fInstallTypes->SetEnabled(true);
|
||||||
|
fDestination->SetEnabled(true);
|
||||||
|
fInstallProcess.Stop();
|
||||||
|
|
||||||
|
BWindow *parent = Window();
|
||||||
|
if (parent && parent->Lock())
|
||||||
|
parent->Quit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case P_MSG_I_ABORT:
|
||||||
|
{
|
||||||
|
BAlert *notify = new BAlert("installation_aborted",
|
||||||
|
T("The installation of the package has been aborted."), T("OK"));
|
||||||
|
notify->Go();
|
||||||
|
fStatusWindow->Hide();
|
||||||
|
fInstall->SetEnabled(true);
|
||||||
|
fInstallTypes->SetEnabled(true);
|
||||||
|
fDestination->SetEnabled(true);
|
||||||
|
fInstallProcess.Stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case P_MSG_I_ERROR:
|
||||||
|
{
|
||||||
|
BAlert *notify = new BAlert("installation_failed", // TODO: Review this
|
||||||
|
T("The requested package failed to install on your system. This "
|
||||||
|
"might be a problem with the target package file. Please consult "
|
||||||
|
"this issue with the package distributor."), T("OK"), NULL,
|
||||||
|
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
||||||
|
fprintf(stderr, "Error while installing the package\n");
|
||||||
|
notify->Go();
|
||||||
|
fStatusWindow->Hide();
|
||||||
|
fInstall->SetEnabled(true);
|
||||||
|
fInstallTypes->SetEnabled(true);
|
||||||
|
fDestination->SetEnabled(true);
|
||||||
|
fInstallProcess.Stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case P_MSG_STOP:
|
||||||
|
{
|
||||||
|
// This message is sent to us by the PackageStatus window, informing
|
||||||
|
// user interruptions.
|
||||||
|
// We actually use this message only when a post installation script
|
||||||
|
// is running and we want to kill it while it's still running
|
||||||
|
fStatusWindow->Hide();
|
||||||
|
fInstall->SetEnabled(true);
|
||||||
|
fInstallTypes->SetEnabled(true);
|
||||||
|
fDestination->SetEnabled(true);
|
||||||
|
fInstallProcess.Stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case B_REFS_RECEIVED:
|
case B_REFS_RECEIVED:
|
||||||
{
|
{
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
@@ -247,122 +283,65 @@ PackageView::MessageReceived(BMessage *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
int32
|
||||||
PackageView::Install()
|
PackageView::ItemExists(PackageItem &item, BPath &path, int32 &policy)
|
||||||
{
|
{
|
||||||
pkg_profile *type = static_cast<pkg_profile *>(fInfo.GetProfile(fCurrentType));
|
int32 choice = P_EXISTS_NONE;
|
||||||
uint32 n = type->items.CountItems();
|
|
||||||
|
|
||||||
fStatusWindow->Reset(n + 4);
|
switch (policy) {
|
||||||
|
case P_EXISTS_OVERWRITE:
|
||||||
|
choice = P_EXISTS_OVERWRITE;
|
||||||
|
break;
|
||||||
|
|
||||||
fStatusWindow->StageStep(1, "Preparing package");
|
case P_EXISTS_SKIP:
|
||||||
|
choice = P_EXISTS_SKIP;
|
||||||
|
break;
|
||||||
|
|
||||||
InstalledPackageInfo packageInfo(fInfo.GetName(), fInfo.GetVersion());
|
case P_EXISTS_ASK:
|
||||||
|
case P_EXISTS_NONE:
|
||||||
|
{
|
||||||
|
BString alertString = T("The ");
|
||||||
|
|
||||||
status_t err = packageInfo.InitCheck();
|
alertString << item.ItemKind() << T(" named \'") << path.Leaf() << "\' ";
|
||||||
err = B_ENTRY_NOT_FOUND;
|
alertString << T("already exists in the given path.\nReplace the file with "
|
||||||
if (err == B_OK) {
|
"the one from this package or skip it?");
|
||||||
// The package is already installed, inform the user
|
|
||||||
BAlert *reinstall = new BAlert("reinstall",
|
|
||||||
T("The given package seems to be already installed on your system. "
|
|
||||||
"Would you like to uninstall the existing one and continue the "
|
|
||||||
"installation?"), T("Continue"), T("Abort"));
|
|
||||||
|
|
||||||
if (reinstall->Go() == 0) {
|
BAlert *alert = new BAlert(T("file_exists"), alertString.String(),
|
||||||
// Uninstall the package
|
T("Replace"), T("Skip"), T("Abort"));
|
||||||
err = packageInfo.Uninstall();
|
|
||||||
if (err != B_OK) {
|
choice = alert->Go();
|
||||||
fprintf(stderr, "Error on uninstall\n");
|
switch (choice) {
|
||||||
return err;
|
case 0:
|
||||||
|
choice = P_EXISTS_OVERWRITE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
choice = P_EXISTS_SKIP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return P_EXISTS_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = packageInfo.SetTo(fInfo.GetName(), fInfo.GetVersion(), true);
|
if (policy == P_EXISTS_NONE) {
|
||||||
if (err != B_OK) {
|
// TODO: Maybe add 'No, but ask again' type of choice as well?
|
||||||
fprintf(stderr, "Error on SetTo\n");
|
alertString = T("Do you want to remember this decision for the rest of "
|
||||||
return err;
|
"this installation?\nAll existing files will be ");
|
||||||
|
alertString << ((choice == P_EXISTS_OVERWRITE)
|
||||||
|
? T("replaced?") : T("skipped?"));
|
||||||
|
|
||||||
|
alert = new BAlert(T("policy_decision"), alertString.String(),
|
||||||
|
T("Yes"), T("No"));
|
||||||
|
|
||||||
|
int32 decision = alert->Go();
|
||||||
|
if (decision == 0)
|
||||||
|
policy = choice;
|
||||||
|
else
|
||||||
|
policy = P_EXISTS_ASK;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else {
|
|
||||||
// Abort the installation
|
|
||||||
return B_FILE_EXISTS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (err == B_ENTRY_NOT_FOUND) {
|
|
||||||
err = packageInfo.SetTo(fInfo.GetName(), fInfo.GetVersion(), true);
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "Error on SetTo\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (fStatusWindow->Stopped())
|
|
||||||
return B_FILE_EXISTS;
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "returning on error\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
fStatusWindow->StageStep(1, "Installing files and folders");
|
return choice;
|
||||||
|
|
||||||
// Install files and directories
|
|
||||||
PackageItem *iter;
|
|
||||||
ItemState state;
|
|
||||||
uint32 i;
|
|
||||||
int32 choice;
|
|
||||||
BString label;
|
|
||||||
|
|
||||||
packageInfo.SetName(fInfo.GetName());
|
|
||||||
// TODO: Here's a small problem, since right now it's not quite sure
|
|
||||||
// which description is really used as such. The one displayed on
|
|
||||||
// the installer is mostly package installation description, but
|
|
||||||
// most people use it for describing the application in more detail
|
|
||||||
// then in the short description.
|
|
||||||
// For now, we'll use the short description if possible.
|
|
||||||
BString description = fInfo.GetShortDescription();
|
|
||||||
if (description.Length() <= 0)
|
|
||||||
description = fInfo.GetDescription();
|
|
||||||
packageInfo.SetDescription(description.String());
|
|
||||||
packageInfo.SetSpaceNeeded(type->space_needed);
|
|
||||||
|
|
||||||
fItemExistsPolicy = P_EXISTS_NONE;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
state.Reset(fItemExistsPolicy); // Reset the current item state
|
|
||||||
iter = static_cast<PackageItem *>(type->items.ItemAt(i));
|
|
||||||
|
|
||||||
err = iter->WriteToPath(fCurrentPath.Path(), &state);
|
|
||||||
if (err == B_FILE_EXISTS) {
|
|
||||||
// Writing to path failed because path already exists - ask the user
|
|
||||||
// what to do and retry the writing process
|
|
||||||
choice = _ItemExists(*iter, state.destination);
|
|
||||||
if (choice != P_EXISTS_ABORT) {
|
|
||||||
state.policy = choice;
|
|
||||||
err = iter->WriteToPath(fCurrentPath.Path(), &state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != B_OK) {
|
|
||||||
fprintf(stderr, "Error while writing path %s\n", fCurrentPath.Path());
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fStatusWindow->Stopped())
|
|
||||||
return B_FILE_EXISTS;
|
|
||||||
label = "";
|
|
||||||
label << (uint32)(i + 1) << " of " << (uint32)n;
|
|
||||||
fStatusWindow->StageStep(1, NULL, label.String());
|
|
||||||
|
|
||||||
packageInfo.AddItem(state.destination.Path());
|
|
||||||
}
|
|
||||||
|
|
||||||
fStatusWindow->StageStep(1, "Finishing installation", "");
|
|
||||||
|
|
||||||
err = packageInfo.Save();
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
fStatusWindow->StageStep(1, "Done");
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -550,68 +529,6 @@ PackageView::_InitProfiles()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
PackageView::_ItemExists(PackageItem &item, BPath &path)
|
|
||||||
{
|
|
||||||
int32 choice = P_EXISTS_NONE;
|
|
||||||
|
|
||||||
switch (fItemExistsPolicy) {
|
|
||||||
case P_EXISTS_OVERWRITE:
|
|
||||||
choice = P_EXISTS_OVERWRITE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case P_EXISTS_SKIP:
|
|
||||||
choice = P_EXISTS_SKIP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case P_EXISTS_ASK:
|
|
||||||
case P_EXISTS_NONE:
|
|
||||||
{
|
|
||||||
BString alertString = T("The ");
|
|
||||||
|
|
||||||
alertString << item.ItemKind() << T(" named \'") << path.Leaf() << "\' ";
|
|
||||||
alertString << T("already exists in the given path.\nReplace the file with "
|
|
||||||
"the one from this package or skip it?");
|
|
||||||
|
|
||||||
BAlert *alert = new BAlert(T("file_exists"), alertString.String(),
|
|
||||||
T("Replace"), T("Skip"), T("Abort"));
|
|
||||||
|
|
||||||
choice = alert->Go();
|
|
||||||
switch (choice) {
|
|
||||||
case 0:
|
|
||||||
choice = P_EXISTS_OVERWRITE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
choice = P_EXISTS_SKIP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return P_EXISTS_ABORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fItemExistsPolicy == P_EXISTS_NONE) {
|
|
||||||
// TODO: Maybe add 'No, but ask again' type of choice as well?
|
|
||||||
alertString = T("Do you want to remember this decision for the rest of "
|
|
||||||
"this installation?\nAll existing files will be ");
|
|
||||||
alertString << ((choice == P_EXISTS_OVERWRITE)
|
|
||||||
? T("replaced?") : T("skipped?"));
|
|
||||||
|
|
||||||
alert = new BAlert(T("policy_decision"), alertString.String(),
|
|
||||||
T("Yes"), T("No"));
|
|
||||||
|
|
||||||
int32 decision = alert->Go();
|
|
||||||
if (decision == 0)
|
|
||||||
fItemExistsPolicy = choice;
|
|
||||||
else
|
|
||||||
fItemExistsPolicy = P_EXISTS_ASK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageView::_GroupChanged(int32 index)
|
PackageView::_GroupChanged(int32 index)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,13 +10,14 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
|
#include "PackageInstall.h"
|
||||||
#include "PackageStatus.h"
|
#include "PackageStatus.h"
|
||||||
|
|
||||||
#include <View.h>
|
|
||||||
#include <Box.h>
|
#include <Box.h>
|
||||||
#include <Button.h>
|
#include <Button.h>
|
||||||
#include <MenuField.h>
|
|
||||||
#include <FilePanel.h>
|
#include <FilePanel.h>
|
||||||
|
#include <MenuField.h>
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
class BPopUpMenu;
|
class BPopUpMenu;
|
||||||
class BTextView;
|
class BTextView;
|
||||||
@@ -37,12 +38,16 @@ class PackageView : public BView {
|
|||||||
void AttachedToWindow();
|
void AttachedToWindow();
|
||||||
void MessageReceived(BMessage *msg);
|
void MessageReceived(BMessage *msg);
|
||||||
|
|
||||||
status_t Install();
|
int32 ItemExists(PackageItem &item, BPath &path, int32 &policy);
|
||||||
|
|
||||||
|
BPath *GetCurrentPath() { return &fCurrentPath; }
|
||||||
|
PackageInfo *GetPackageInfo() { return &fInfo; }
|
||||||
|
uint32 GetCurrentType() { return fCurrentType; }
|
||||||
|
PackageStatus *GetStatusWindow() { return fStatusWindow; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _InitView();
|
void _InitView();
|
||||||
void _InitProfiles();
|
void _InitProfiles();
|
||||||
int32 _ItemExists(PackageItem &item, BPath &path);
|
|
||||||
|
|
||||||
status_t _GroupChanged(int32 index);
|
status_t _GroupChanged(int32 index);
|
||||||
|
|
||||||
@@ -55,10 +60,10 @@ class PackageView : public BView {
|
|||||||
BFilePanel *fOpenPanel;
|
BFilePanel *fOpenPanel;
|
||||||
BPath fCurrentPath;
|
BPath fCurrentPath;
|
||||||
uint32 fCurrentType;
|
uint32 fCurrentType;
|
||||||
int32 fItemExistsPolicy;
|
|
||||||
|
|
||||||
PackageInfo fInfo;
|
PackageInfo fInfo;
|
||||||
PackageStatus *fStatusWindow;
|
PackageStatus *fStatusWindow;
|
||||||
|
PackageInstall fInstallProcess;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PACKAGE_VIEW_H
|
#endif // PACKAGE_VIEW_H
|
||||||
|
|||||||
Reference in New Issue
Block a user