* Applied patch by sil2100 that basically adds a "Yes to all" button, see

ticket #4059. I fixed a few style violations, though. Thanks!
* Automatic whitespace cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32161 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-08-06 15:00:52 +00:00
parent 1a60fd72cf
commit fc11b80c6c
4 changed files with 307 additions and 198 deletions
+151 -144
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007-2009, Haiku, Inc. * Copyright 2007-2009, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Author: * Author:
@@ -9,16 +9,19 @@
#include "PackageItem.h" #include "PackageItem.h"
#include <string.h>
#include <Alert.h> #include <Alert.h>
#include <ByteOrder.h> #include <ByteOrder.h>
#include <Directory.h> #include <Directory.h>
#include <fs_info.h>
#include <NodeInfo.h> #include <NodeInfo.h>
#include <SymLink.h> #include <SymLink.h>
#include <Volume.h> #include <Volume.h>
#include <fs_info.h>
#include "zlib.h" #include "zlib.h"
// Macro reserved for later localization // Macro reserved for later localization
#define T(x) x #define T(x) x
@@ -37,7 +40,7 @@ enum {
status_t status_t
inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize) inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize)
{ {
z_stream stream; z_stream stream;
stream.zalloc = Z_NULL; stream.zalloc = Z_NULL;
stream.zfree = Z_NULL; stream.zfree = Z_NULL;
@@ -146,7 +149,7 @@ PackageItem::~PackageItem()
void void
PackageItem::SetTo(BFile *parent, const BString &path, uint8 type, uint32 ctime, PackageItem::SetTo(BFile *parent, const BString &path, uint8 type, uint32 ctime,
uint32 mtime, uint64 offset, uint64 size) uint32 mtime, uint64 offset, uint64 size)
{ {
fPackage = parent; fPackage = parent;
@@ -160,25 +163,6 @@ PackageItem::SetTo(BFile *parent, const BString &path, uint8 type, uint32 ctime,
} }
int32
PackageItem::ItemExists(const char *name)
{
// TODO: this function doesn't really fit in, the GUI should be separated
// from the package engine completely
BString alertString = "The ";
alertString << ItemKind() << " named \'" << name << "\' ";
alertString << T("already exists in the given path. Should I replace "
"the existing file with the one from this package?");
BAlert *alert = new BAlert(T("file_exists"), alertString.String(),
T("Yes"), T("No"), T("Abort"));
return alert->Go();
}
status_t status_t
PackageItem::InitPath(const char *path, BPath *destination) PackageItem::InitPath(const char *path, BPath *destination)
{ {
@@ -218,7 +202,7 @@ PackageItem::InitPath(const char *path, BPath *destination)
status_t status_t
PackageItem::HandleAttributes(BPath *destination, BNode *node, PackageItem::HandleAttributes(BPath *destination, BNode *node,
const char *header) const char *header)
{ {
status_t ret = B_OK; status_t ret = B_OK;
@@ -256,7 +240,7 @@ PackageItem::HandleAttributes(BPath *destination, BNode *node,
continue; continue;
ret = ParseAttribute(buffer, node, &attrName, &nameSize, &attrType, ret = ParseAttribute(buffer, node, &attrName, &nameSize, &attrType,
&attrData, &dataSize, &temp, &tempSize, &attrCSize, &attrOSize, &attrData, &dataSize, &temp, &tempSize, &attrCSize, &attrOSize,
&attrStarted, &done); &attrStarted, &done);
if (ret != B_OK || done) { if (ret != B_OK || done) {
if (ret != B_OK) { if (ret != B_OK) {
@@ -276,9 +260,9 @@ PackageItem::HandleAttributes(BPath *destination, BNode *node,
status_t status_t
PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName, PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
uint32 *nameSize, uint32 *attrType, uint8 **attrData, uint64 *dataSize, uint32 *nameSize, uint32 *attrType, uint8 **attrData, uint64 *dataSize,
uint8 **temp, uint64 *tempSize, uint64 *attrCSize, uint64 *attrOSize, uint8 **temp, uint64 *tempSize, uint64 *attrCSize, uint64 *attrOSize,
bool *attrStarted, bool *done) bool *attrStarted, bool *done)
{ {
status_t ret = B_OK; status_t ret = B_OK;
@@ -320,7 +304,7 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
parser_debug(" BeAT.\n"); parser_debug(" BeAT.\n");
fPackage->Read(attrType, 4); fPackage->Read(attrType, 4);
swap_data(B_UINT32_TYPE, attrType, sizeof(*attrType), swap_data(B_UINT32_TYPE, attrType, sizeof(*attrType),
B_SWAP_BENDIAN_TO_HOST); B_SWAP_BENDIAN_TO_HOST);
} else if (!memcmp(buffer, "BeAD", 5)) { } else if (!memcmp(buffer, "BeAD", 5)) {
if (!*attrStarted) { if (!*attrStarted) {
@@ -330,11 +314,11 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
parser_debug(" BeAD.\n"); parser_debug(" BeAD.\n");
fPackage->Read(attrCSize, 8); fPackage->Read(attrCSize, 8);
swap_data(B_UINT64_TYPE, attrCSize, sizeof(*attrCSize), swap_data(B_UINT64_TYPE, attrCSize, sizeof(*attrCSize),
B_SWAP_BENDIAN_TO_HOST); B_SWAP_BENDIAN_TO_HOST);
fPackage->Read(attrOSize, 8); fPackage->Read(attrOSize, 8);
swap_data(B_UINT64_TYPE, attrOSize, sizeof(*attrOSize), swap_data(B_UINT64_TYPE, attrOSize, sizeof(*attrOSize),
B_SWAP_BENDIAN_TO_HOST); B_SWAP_BENDIAN_TO_HOST);
fPackage->Seek(4, SEEK_CUR); // TODO: Check what this means fPackage->Seek(4, SEEK_CUR); // TODO: Check what this means
@@ -350,7 +334,7 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
*attrData = new uint8[*dataSize]; *attrData = new uint8[*dataSize];
} }
if (fPackage->Read(*temp, *attrCSize) if (fPackage->Read(*temp, *attrCSize)
!= static_cast<ssize_t>(*attrCSize)) { != static_cast<ssize_t>(*attrCSize)) {
ret = B_ERROR; ret = B_ERROR;
return ret; return ret;
@@ -367,7 +351,7 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
} }
parser_debug(" Padding.\n"); parser_debug(" Padding.\n");
ssize_t wrote = node->WriteAttr(*attrName, *attrType, 0, *attrData, ssize_t wrote = node->WriteAttr(*attrName, *attrType, 0, *attrData,
*attrOSize); *attrOSize);
if (wrote != static_cast<ssize_t>(*attrOSize)) { if (wrote != static_cast<ssize_t>(*attrOSize)) {
parser_debug("Failed to write attribute %s %s\n", *attrName, strerror(wrote)); parser_debug("Failed to write attribute %s %s\n", *attrName, strerror(wrote));
@@ -391,7 +375,7 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
status_t status_t
PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize, PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
bool *done) bool *done)
{ {
status_t ret = B_OK; status_t ret = B_OK;
@@ -400,11 +384,11 @@ PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
parser_debug(" Found file data.\n"); parser_debug(" Found file data.\n");
uint64 compressed, original; uint64 compressed, original;
fPackage->Read(&compressed, 8); fPackage->Read(&compressed, 8);
swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64), swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64),
B_SWAP_BENDIAN_TO_HOST); B_SWAP_BENDIAN_TO_HOST);
fPackage->Read(&original, 8); fPackage->Read(&original, 8);
swap_data(B_UINT64_TYPE, &original, sizeof(uint64), swap_data(B_UINT64_TYPE, &original, sizeof(uint64),
B_SWAP_BENDIAN_TO_HOST); B_SWAP_BENDIAN_TO_HOST);
parser_debug(" Still good... (%llu : %llu)\n", original, parser_debug(" Still good... (%llu : %llu)\n", original,
originalSize); originalSize);
@@ -446,25 +430,28 @@ PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
PackageDirectory::PackageDirectory(BFile *parent, const BString &path, PackageDirectory::PackageDirectory(BFile *parent, const BString &path,
uint8 type, uint32 ctime, uint32 mtime, uint64 offset, uint64 size) uint8 type, uint32 ctime, uint32 mtime, uint64 offset, uint64 size)
: PackageItem(parent, path, type, ctime, mtime, offset, size) :
PackageItem(parent, path, type, ctime, mtime, offset, size)
{ {
} }
status_t status_t
PackageDirectory::WriteToPath(const char *path, BPath *final) PackageDirectory::WriteToPath(const char *path, ItemState *state)
{ {
BPath destination; BPath &destination = state->destination;
status_t ret; status_t ret;
parser_debug("Directory: %s WriteToPath() called!\n", fPath.String()); parser_debug("Directory: %s WriteToPath() called!\n", fPath.String());
ret = InitPath(path, &destination); ret = InitPath(path, &destination);
parser_debug("Ret: %d %s\n", ret, strerror(ret));
if (ret != B_OK) if (ret != B_OK)
return ret; return ret;
// Since Haiku is single-user right now, we give the newly // Since Haiku is single-user right now, we give the newly
// created directory default permissions // created directory default permissions
ret = create_directory(destination.Path(), kDefaultMode); ret = create_directory(destination.Path(), kDefaultMode);
parser_debug("Create dir ret: %d %s\n", ret, strerror(ret));
if (ret != B_OK) if (ret != B_OK)
return ret; return ret;
BDirectory dir(destination.Path()); BDirectory dir(destination.Path());
@@ -472,7 +459,7 @@ PackageDirectory::WriteToPath(const char *path, BPath *final)
if (fCreationTime) if (fCreationTime)
dir.SetCreationTime(static_cast<time_t>(fCreationTime)); dir.SetCreationTime(static_cast<time_t>(fCreationTime));
if (fModificationTime) if (fModificationTime)
dir.SetModificationTime(static_cast<time_t>(fModificationTime)); dir.SetModificationTime(static_cast<time_t>(fModificationTime));
@@ -480,10 +467,8 @@ PackageDirectory::WriteToPath(const char *path, BPath *final)
// we can check here whether it is necessary to continue // we can check here whether it is necessary to continue
if (fOffset) if (fOffset)
ret = HandleAttributes(&destination, &dir, "FoDa"); ret = HandleAttributes(&destination, &dir, "FoDa");
if (final)
*final = destination;
parser_debug("Ret: %d %s\n", ret, strerror(ret));
return ret; return ret;
} }
@@ -502,7 +487,8 @@ PackageFile::PackageFile(BFile *parent, const BString &path, uint8 type,
uint32 ctime, uint32 mtime, uint64 offset, uint64 size, uint32 ctime, uint32 mtime, uint64 offset, uint64 size,
uint64 originalSize, uint32 platform, const BString &mime, uint64 originalSize, uint32 platform, const BString &mime,
const BString &signature, uint32 mode) const BString &signature, uint32 mode)
: PackageItem(parent, path, type, ctime, mtime, offset, size), :
PackageItem(parent, path, type, ctime, mtime, offset, size),
fOriginalSize(originalSize), fOriginalSize(originalSize),
fPlatform(platform), fPlatform(platform),
fMode(mode), fMode(mode),
@@ -513,43 +499,55 @@ PackageFile::PackageFile(BFile *parent, const BString &path, uint8 type,
status_t status_t
PackageFile::WriteToPath(const char *path, BPath *final) PackageFile::WriteToPath(const char *path, ItemState *state)
{ {
BPath destination; if (state == NULL)
status_t ret; return B_ERROR;
BPath &destination = state->destination;
status_t ret = B_OK;
parser_debug("File: %s WriteToPath() called!\n", fPath.String()); parser_debug("File: %s WriteToPath() called!\n", fPath.String());
ret = InitPath(path, &destination); BFile file;
if (ret != B_OK) if (state->status == B_NO_INIT || destination.InitCheck() != B_OK) {
return ret; ret = InitPath(path, &destination);
BFile file(destination.Path(),
B_WRITE_ONLY | B_CREATE_FILE | B_FAIL_IF_EXISTS);
ret = file.InitCheck();
if (ret == B_FILE_EXISTS) {
int32 selection = ItemExists(destination.Leaf());
switch (selection) {
case 0:
ret = file.SetTo(destination.Path(),
B_WRITE_ONLY | B_ERASE_FILE);
if (ret != B_OK)
return ret;
break;
case 1:
return B_OK;
default:
return B_FILE_EXISTS;
}
} else if (ret == B_ENTRY_NOT_FOUND) {
BPath directory;
destination.GetParent(&directory);
if (create_directory(directory.Path(), kDefaultMode) != B_OK)
return B_ERROR;
ret = file.SetTo(destination.Path(), B_WRITE_ONLY | B_CREATE_FILE);
if (ret != B_OK) if (ret != B_OK)
return ret; return ret;
} else if (ret != B_OK)
ret = file.SetTo(destination.Path(),
B_WRITE_ONLY | B_CREATE_FILE | B_FAIL_IF_EXISTS);
if (ret == B_ENTRY_NOT_FOUND) {
BPath directory;
destination.GetParent(&directory);
if (create_directory(directory.Path(), kDefaultMode) != B_OK)
return B_ERROR;
ret = file.SetTo(destination.Path(), B_WRITE_ONLY | B_CREATE_FILE);
} else if (ret == B_FILE_EXISTS)
state->status = B_FILE_EXISTS;
if (ret != B_OK)
return ret;
}
if (state->status == B_FILE_EXISTS) {
switch (state->policy) {
case P_EXISTS_OVERWRITE:
ret = file.SetTo(destination.Path(),
B_WRITE_ONLY | B_ERASE_FILE);
break;
case P_EXISTS_NONE:
case P_EXISTS_ASK:
ret = B_FILE_EXISTS;
break;
case P_EXISTS_SKIP:
return B_OK;
}
}
if (ret != B_OK)
return ret; return ret;
parser_debug(" File created!\n"); parser_debug(" File created!\n");
@@ -563,7 +561,7 @@ PackageFile::WriteToPath(const char *path, BPath *final)
if (ret != B_OK) if (ret != B_OK)
return ret; return ret;
// Set the mimetype and application signature if present // Set the mimetype and application signature if present
BNodeInfo info(&file); BNodeInfo info(&file);
if (fMimeType.Length() > 0) { if (fMimeType.Length() > 0) {
@@ -600,7 +598,7 @@ PackageFile::WriteToPath(const char *path, BPath *final)
uint64 attrCSize = 0, attrOSize = 0; uint64 attrCSize = 0, attrOSize = 0;
uint32 attrType = 0; // type_code type uint32 attrType = 0; // type_code type
bool attrStarted = false, done = false; bool attrStarted = false, done = false;
uint8 section = P_ATTRIBUTE; uint8 section = P_ATTRIBUTE;
while (fPackage->Read(buffer, 7) == 7) { while (fPackage->Read(buffer, 7) == 7) {
@@ -637,9 +635,6 @@ PackageFile::WriteToPath(const char *path, BPath *final)
delete[] temp; delete[] temp;
} }
if (final)
*final = destination;
return ret; return ret;
} }
@@ -657,7 +652,8 @@ PackageFile::ItemKind()
PackageLink::PackageLink(BFile *parent, const BString &path, PackageLink::PackageLink(BFile *parent, const BString &path,
const BString &link, uint8 type, uint32 ctime, uint32 mtime, const BString &link, uint8 type, uint32 ctime, uint32 mtime,
uint32 mode, uint64 offset, uint64 size) uint32 mode, uint64 offset, uint64 size)
: PackageItem(parent, path, type, ctime, mtime, offset, size), :
PackageItem(parent, path, type, ctime, mtime, offset, size),
fMode(mode), fMode(mode),
fLink(link) fLink(link)
{ {
@@ -665,73 +661,88 @@ PackageLink::PackageLink(BFile *parent, const BString &path,
status_t status_t
PackageLink::WriteToPath(const char *path, BPath *final) PackageLink::WriteToPath(const char *path, ItemState *state)
{ {
if (state == NULL)
return B_ERROR;
status_t ret = B_OK;
BSymLink symlink;
parser_debug("Symlink: %s WriteToPath() called!\n", fPath.String()); parser_debug("Symlink: %s WriteToPath() called!\n", fPath.String());
BPath destination; BPath &destination = state->destination;
status_t ret = InitPath(path, &destination); BDirectory *dir = &state->parent;
if (ret != B_OK)
return ret;
BString linkName(destination.Leaf()); if (state->status == B_NO_INIT || destination.InitCheck() != B_OK
parser_debug("%s:%s:%s\n", fPath.String(), destination.Path(), || dir->InitCheck() != B_OK) {
linkName.String()); // Not yet initialized
ret = InitPath(path, &destination);
if (ret != B_OK)
return ret;
BPath dirPath; BString linkName(destination.Leaf());
ret = destination.GetParent(&dirPath); parser_debug("%s:%s:%s\n", fPath.String(), destination.Path(),
BDirectory dir(dirPath.Path()); linkName.String());
ret = dir.InitCheck(); BPath dirPath;
if (ret == B_ENTRY_NOT_FOUND) { ret = destination.GetParent(&dirPath);
if ((ret = create_directory(dirPath.Path(), kDefaultMode)) != B_OK) { ret = dir->SetTo(dirPath.Path());
parser_debug("create_directory()) failed\n");
return B_ERROR;
}
}
if (ret != B_OK) {
parser_debug("destination InitCheck failed %s for %s\n", strerror(ret), dirPath.Path());
return ret;
}
BSymLink symlink; if (ret == B_ENTRY_NOT_FOUND) {
ret = dir.CreateSymLink(destination.Path(), fLink.String(), &symlink); ret = create_directory(dirPath.Path(), kDefaultMode);
if (ret == B_FILE_EXISTS) { if (ret != B_OK) {
// We need to check if the existing symlink is pointing at the same path parser_debug("create_directory()) failed\n");
// as our new one - if not, let's prompt the user return B_ERROR;
symlink.SetTo(destination.Path());
BPath oldLink;
ret = symlink.MakeLinkedPath(&dir, &oldLink);
chdir(dirPath.Path());
if (ret == B_BAD_VALUE || oldLink != fLink.String()) {
// The old symlink is different (or not a symlink) - ask the user
int32 selection = ItemExists(destination.Leaf());
switch (selection) {
case 0:
{
symlink.Unset();
BEntry entry;
ret = entry.SetTo(destination.Path());
if (ret != B_OK)
return ret;
entry.Remove();
ret = dir.CreateSymLink(destination.Path(), fLink.String(),
&symlink);
break;
}
case 1:
parser_debug("Skipping already existent SymLink\n");
return B_OK;
default:
ret = B_FILE_EXISTS;
} }
} else { }
ret = B_OK; if (ret != B_OK) {
parser_debug("destination InitCheck failed %s for %s\n",
strerror(ret), dirPath.Path());
return ret;
}
ret = dir->CreateSymLink(destination.Path(), fLink.String(), &symlink);
if (ret == B_FILE_EXISTS) {
// We need to check if the existing symlink is pointing at the same path
// as our new one - if not, let's prompt the user
symlink.SetTo(destination.Path());
BPath oldLink;
ret = symlink.MakeLinkedPath(dir, &oldLink);
chdir(dirPath.Path());
if (ret == B_BAD_VALUE || oldLink != fLink.String())
state->status = ret = B_FILE_EXISTS;
else
ret = B_OK;
} }
} }
if (state->status == B_FILE_EXISTS) {
switch (state->policy) {
case P_EXISTS_OVERWRITE:
{
BEntry entry;
ret = entry.SetTo(destination.Path());
if (ret != B_OK)
return ret;
entry.Remove();
ret = dir->CreateSymLink(destination.Path(), fLink.String(),
&symlink);
break;
}
case P_EXISTS_NONE:
case P_EXISTS_ASK:
ret = B_FILE_EXISTS;
break;
case P_EXISTS_SKIP:
return B_OK;
}
}
if (ret != B_OK) { if (ret != B_OK) {
parser_debug("CreateSymLink failed\n"); parser_debug("CreateSymLink failed\n");
return ret; return ret;
@@ -743,7 +754,7 @@ PackageLink::WriteToPath(const char *path, BPath *final)
if (fCreationTime && ret == B_OK) if (fCreationTime && ret == B_OK)
ret = symlink.SetCreationTime(static_cast<time_t>(fCreationTime)); ret = symlink.SetCreationTime(static_cast<time_t>(fCreationTime));
if (fModificationTime && ret == B_OK) { if (fModificationTime && ret == B_OK) {
ret = symlink.SetModificationTime(static_cast<time_t>( ret = symlink.SetModificationTime(static_cast<time_t>(
fModificationTime)); fModificationTime));
@@ -759,10 +770,6 @@ PackageLink::WriteToPath(const char *path, BPath *final)
ret = HandleAttributes(&destination, &symlink, "LnDa"); ret = HandleAttributes(&destination, &symlink, "LnDa");
} }
if (final) {
*final = destination;
}
return ret; return ret;
} }
+38 -16
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, Haiku, Inc. * Copyright 2007-2009, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Author: * Author:
@@ -11,6 +11,7 @@
#include <stdio.h> #include <stdio.h>
#include <Directory.h>
#include <Entry.h> #include <Entry.h>
#include <File.h> #include <File.h>
#include <Path.h> #include <Path.h>
@@ -32,10 +33,38 @@ enum {
P_USER_PATH P_USER_PATH
}; };
// Existing item overwriting policy of a single file
enum {
P_EXISTS_ASK = 0,
P_EXISTS_OVERWRITE,
P_EXISTS_SKIP,
P_EXISTS_ABORT,
P_EXISTS_NONE
};
extern status_t inflate_data(uint8* in, uint32 inSize, uint8* out, extern status_t inflate_data(uint8* in, uint32 inSize, uint8* out,
uint32 outSize); uint32 outSize);
struct ItemState {
ItemState() : policy(P_EXISTS_NONE), status(B_NO_INIT) {}
~ItemState() {}
inline void Reset(int32 currentPolicy)
{
destination.Unset();
parent.Unset();
status = B_NO_INIT;
policy = currentPolicy;
}
BPath destination;
BDirectory parent;
uint8 policy;
status_t status;
};
class PackageItem { class PackageItem {
public: public:
PackageItem(BFile* parent, const BString& path, PackageItem(BFile* parent, const BString& path,
@@ -44,16 +73,15 @@ public:
virtual ~PackageItem(); virtual ~PackageItem();
virtual status_t WriteToPath(const char* path = NULL, virtual status_t WriteToPath(const char* path = NULL,
BPath* final = 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;
protected: protected:
virtual const char* ItemKind() = 0;
int32 ItemExists(const char* name);
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);
status_t ParseAttribute(uint8* buffer, BNode* node, status_t ParseAttribute(uint8* buffer, BNode* node,
@@ -84,9 +112,7 @@ public:
uint64 offset = 0, uint64 size = 0); uint64 offset = 0, uint64 size = 0);
virtual status_t WriteToPath(const char* path = NULL, virtual status_t WriteToPath(const char* path = NULL,
BPath* final = NULL); ItemState *state = NULL);
protected:
virtual const char* ItemKind(); virtual const char* ItemKind();
}; };
@@ -100,16 +126,14 @@ public:
const BString& signature, uint32 mode); const BString& signature, uint32 mode);
virtual status_t WriteToPath(const char* path = NULL, virtual status_t WriteToPath(const char* path = NULL,
BPath* final = NULL); ItemState *state = NULL);
protected:
virtual const char* ItemKind(); virtual const char* ItemKind();
private: private:
uint64 fOriginalSize; uint64 fOriginalSize;
uint32 fPlatform; uint32 fPlatform;
uint32 fMode; uint32 fMode;
BString fMimeType; BString fMimeType;
BString fSignature; BString fSignature;
}; };
@@ -119,13 +143,11 @@ class PackageLink : public PackageItem {
public: public:
PackageLink(BFile* parent, const BString& path, PackageLink(BFile* parent, const BString& path,
const BString& link, uint8 type, uint32 ctime, const BString& link, uint8 type, uint32 ctime,
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 WriteToPath(const char* path = NULL,
BPath* final = NULL); ItemState *state = NULL);
protected:
virtual const char* ItemKind(); virtual const char* ItemKind();
private: private:
+114 -36
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, Haiku, Inc. * Copyright 2007-2009, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Author: * Author:
@@ -69,7 +69,7 @@ PackageView::PackageView(BRect frame, const entry_ref *ref)
// Check whether the package has been successfuly parsed // Check whether the package has been successfuly parsed
status_t ret = fInfo.InitCheck(); status_t ret = fInfo.InitCheck();
if (ret == B_OK) if (ret == B_OK)
_InitProfiles(); _InitProfiles();
ResizeTo(Bounds().Width(), fInstall->Frame().bottom + 4); ResizeTo(Bounds().Width(), fInstall->Frame().bottom + 4);
@@ -129,7 +129,7 @@ PackageView::AttachedToWindow()
PackageImageViewer *imageViewer = new PackageImageViewer(image); PackageImageViewer *imageViewer = new PackageImageViewer(image);
imageViewer->Go(); imageViewer->Go();
} }
// 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) {
@@ -175,14 +175,14 @@ PackageView::MessageReceived(BMessage *msg)
notify = new BAlert("installation_failed", // TODO: Review this notify = new BAlert("installation_failed", // TODO: Review this
T("The requested package failed to install on your system. This " T("The requested package failed to install on your system. This "
"might be a problem with the target package file. Please consult " "might be a problem with the target package file. Please consult "
"this issue with the package distributor."), T("OK"), NULL, "this issue with the package distributor."), T("OK"), NULL,
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
fprintf(stderr, "Error while installing the package : %s\n", strerror(ret)); fprintf(stderr, "Error while installing the package : %s\n", strerror(ret));
} }
notify->Go(); notify->Go();
fStatusWindow->Hide(); fStatusWindow->Hide();
fInstall->SetEnabled(true); fInstall->SetEnabled(true);
break; break;
} }
case P_MSG_PATH_CHANGED: case P_MSG_PATH_CHANGED:
@@ -196,7 +196,7 @@ PackageView::MessageReceived(BMessage *msg)
case P_MSG_OPEN_PANEL: case P_MSG_OPEN_PANEL:
fOpenPanel->Show(); fOpenPanel->Show();
break; break;
case P_MSG_GROUP_CHANGED: case P_MSG_GROUP_CHANGED:
{ {
int32 index; int32 index;
if (msg->FindInt32("index", &index) == B_OK) { if (msg->FindInt32("index", &index) == B_OK) {
@@ -267,7 +267,7 @@ PackageView::Install()
T("The given package seems to be already installed on your system. " T("The given package seems to be already installed on your system. "
"Would you like to uninstall the existing one and continue the " "Would you like to uninstall the existing one and continue the "
"installation?"), T("Yes"), T("No")); "installation?"), T("Yes"), T("No"));
if (reinstall->Go() == 0) { if (reinstall->Go() == 0) {
// Uninstall the package // Uninstall the package
err = packageInfo.Uninstall(); err = packageInfo.Uninstall();
@@ -305,10 +305,11 @@ PackageView::Install()
// Install files and directories // Install files and directories
PackageItem *iter; PackageItem *iter;
BPath installedTo; ItemState state;
uint32 i; uint32 i;
int32 choice;
BString label; BString label;
packageInfo.SetName(fInfo.GetName()); packageInfo.SetName(fInfo.GetName());
// TODO: Here's a small problem, since right now it's not quite sure // 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 // which description is really used as such. The one displayed on
@@ -322,20 +323,35 @@ PackageView::Install()
packageInfo.SetDescription(description.String()); packageInfo.SetDescription(description.String());
packageInfo.SetSpaceNeeded(type->space_needed); packageInfo.SetSpaceNeeded(type->space_needed);
fItemExistsPolicy = P_EXISTS_NONE;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
state.Reset(fItemExistsPolicy); // Reset the current item state
iter = static_cast<PackageItem *>(type->items.ItemAt(i)); iter = static_cast<PackageItem *>(type->items.ItemAt(i));
err = iter->WriteToPath(fCurrentPath.Path(), &installedTo);
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) { if (err != B_OK) {
fprintf(stderr, "Error while writing path %s\n", fCurrentPath.Path()); fprintf(stderr, "Error while writing path %s\n", fCurrentPath.Path());
return err; return err;
} }
if (fStatusWindow->Stopped()) if (fStatusWindow->Stopped())
return B_FILE_EXISTS; return B_FILE_EXISTS;
label = ""; label = "";
label << (uint32)(i + 1) << " of " << (uint32)n; label << (uint32)(i + 1) << " of " << (uint32)n;
fStatusWindow->StageStep(1, NULL, label.String()); fStatusWindow->StageStep(1, NULL, label.String());
packageInfo.AddItem(installedTo.Path()); packageInfo.AddItem(state.destination.Path());
} }
fStatusWindow->StageStep(1, "Finishing installation", ""); fStatusWindow->StageStep(1, "Finishing installation", "");
@@ -355,7 +371,7 @@ void
PackageView::_InitView() PackageView::_InitView()
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BTextView *description = new BTextView(BRect(0, 0, 20, 20), "description", BTextView *description = new BTextView(BRect(0, 0, 20, 20), "description",
BRect(4, 4, 16, 16), B_FOLLOW_NONE, B_WILL_DRAW); BRect(4, 4, 16, 16), B_FOLLOW_NONE, B_WILL_DRAW);
description->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); description->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
@@ -370,15 +386,15 @@ PackageView::_InitView()
installType->SetAlignment(B_ALIGN_RIGHT); installType->SetAlignment(B_ALIGN_RIGHT);
installType->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); installType->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE));
fInstallDesc = new BTextView(BRect(0, 0, 10, 10), "install_desc", fInstallDesc = new BTextView(BRect(0, 0, 10, 10), "install_desc",
BRect(2, 2, 8, 8), B_FOLLOW_NONE, B_WILL_DRAW); BRect(2, 2, 8, 8), B_FOLLOW_NONE, B_WILL_DRAW);
fInstallDesc->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); fInstallDesc->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fInstallDesc->MakeEditable(false); fInstallDesc->MakeEditable(false);
fInstallDesc->MakeSelectable(false); fInstallDesc->MakeSelectable(false);
fInstallDesc->SetText(T("No installation type selected")); fInstallDesc->SetText(T("No installation type selected"));
fInstallDesc->TextHeight(0, fInstallDesc->TextLength()); fInstallDesc->TextHeight(0, fInstallDesc->TextLength());
fInstall = new BButton("install_button", T("Install"), fInstall = new BButton("install_button", T("Install"),
new BMessage(P_MSG_INSTALL)); new BMessage(P_MSG_INSTALL));
BView *installField = BGroupLayoutBuilder(B_VERTICAL, 5.0f) BView *installField = BGroupLayoutBuilder(B_VERTICAL, 5.0f)
@@ -400,7 +416,7 @@ PackageView::_InitView()
.End(); .End();
AddChild(root); AddChild(root);
fInstall->MakeDefault(true); fInstall->MakeDefault(true);
}*/ }*/
@@ -409,7 +425,7 @@ void
PackageView::_InitView() PackageView::_InitView()
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BRect rect = Bounds(); BRect rect = Bounds();
BTextView *description = new BTextView(rect, "description", BTextView *description = new BTextView(rect, "description",
rect.InsetByCopy(5, 5), B_FOLLOW_NONE, B_WILL_DRAW); rect.InsetByCopy(5, 5), B_FOLLOW_NONE, B_WILL_DRAW);
@@ -424,7 +440,7 @@ PackageView::_InitView()
description->ResizeTo(rect.Width() - B_V_SCROLL_BAR_WIDTH, kMaxDescHeight); description->ResizeTo(rect.Width() - B_V_SCROLL_BAR_WIDTH, kMaxDescHeight);
BScrollView *scroller = new BScrollView("desciption_view", description, BScrollView *scroller = new BScrollView("desciption_view", description,
B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_NO_BORDER); B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_NO_BORDER);
AddChild(scroller); AddChild(scroller);
rect = scroller->Frame(); rect = scroller->Frame();
} }
@@ -433,24 +449,24 @@ PackageView::_InitView()
AddChild(description); AddChild(description);
rect = description->Frame(); rect = description->Frame();
} }
rect.top = rect.bottom + 2; rect.top = rect.bottom + 2;
rect.bottom += 100; rect.bottom += 100;
BBox *installBox = new BBox(rect.InsetByCopy(2, 2), "install_box"); BBox *installBox = new BBox(rect.InsetByCopy(2, 2), "install_box");
fInstallTypes = new BPopUpMenu("none"); fInstallTypes = new BPopUpMenu("none");
BMenuField *installType = new BMenuField(BRect(2, 2, 100, 50), "install_type", BMenuField *installType = new BMenuField(BRect(2, 2, 100, 50), "install_type",
T("Installation type:"), fInstallTypes, false); T("Installation type:"), fInstallTypes, false);
installType->SetDivider(installType->StringWidth(installType->Label()) + 8); installType->SetDivider(installType->StringWidth(installType->Label()) + 8);
installType->SetAlignment(B_ALIGN_RIGHT); installType->SetAlignment(B_ALIGN_RIGHT);
installType->ResizeToPreferred(); installType->ResizeToPreferred();
installBox->AddChild(installType); installBox->AddChild(installType);
rect = installBox->Bounds().InsetBySelf(4, 4); rect = installBox->Bounds().InsetBySelf(4, 4);
rect.top = installType->Frame().bottom; rect.top = installType->Frame().bottom;
fInstallDesc = new BTextView(rect, "install_desc", fInstallDesc = new BTextView(rect, "install_desc",
BRect(2, 2, rect.Width() - 2, rect.Height() - 2), B_FOLLOW_NONE, BRect(2, 2, rect.Width() - 2, rect.Height() - 2), B_FOLLOW_NONE,
B_WILL_DRAW); B_WILL_DRAW);
fInstallDesc->MakeEditable(false); fInstallDesc->MakeEditable(false);
@@ -461,28 +477,28 @@ PackageView::_InitView()
fInstallDesc->ResizeTo(rect.Width() - B_V_SCROLL_BAR_WIDTH, 60); fInstallDesc->ResizeTo(rect.Width() - B_V_SCROLL_BAR_WIDTH, 60);
BScrollView *scroller = new BScrollView("desciption_view", fInstallDesc, BScrollView *scroller = new BScrollView("desciption_view", fInstallDesc,
B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_NO_BORDER); B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_NO_BORDER);
installBox->ResizeTo(installBox->Bounds().Width(), installBox->ResizeTo(installBox->Bounds().Width(),
scroller->Frame().bottom + 10); scroller->Frame().bottom + 10);
installBox->AddChild(scroller); installBox->AddChild(scroller);
AddChild(installBox); AddChild(installBox);
fDestination = new BPopUpMenu("none"); fDestination = new BPopUpMenu("none");
rect = installBox->Frame(); rect = installBox->Frame();
rect.top = rect.bottom + 5; rect.top = rect.bottom + 5;
rect.bottom += 35; rect.bottom += 35;
fDestField = new BMenuField(rect, "install_to", T("Install to:"), fDestField = new BMenuField(rect, "install_to", T("Install to:"),
fDestination, false); fDestination, false);
fDestField->SetDivider(fDestField->StringWidth(fDestField->Label()) + 8); fDestField->SetDivider(fDestField->StringWidth(fDestField->Label()) + 8);
fDestField->SetAlignment(B_ALIGN_RIGHT); fDestField->SetAlignment(B_ALIGN_RIGHT);
fDestField->ResizeToPreferred(); fDestField->ResizeToPreferred();
AddChild(fDestField); AddChild(fDestField);
fInstall = new BButton(rect, "install_button", T("Install"), fInstall = new BButton(rect, "install_button", T("Install"),
new BMessage(P_MSG_INSTALL)); new BMessage(P_MSG_INSTALL));
fInstall->ResizeToPreferred(); fInstall->ResizeToPreferred();
AddChild(fInstall); AddChild(fInstall);
@@ -506,7 +522,7 @@ PackageView::_InitProfiles()
prof = fInfo.GetProfile(0); prof = fInfo.GetProfile(0);
convert_size(prof->space_needed, sizeString, 32); convert_size(prof->space_needed, sizeString, 32);
name << prof->name << " (" << sizeString << ")"; name << prof->name << " (" << sizeString << ")";
message = new BMessage(P_MSG_GROUP_CHANGED); message = new BMessage(P_MSG_GROUP_CHANGED);
message->AddInt32("index", 0); message->AddInt32("index", 0);
item = new BMenuItem(name.String(), message); item = new BMenuItem(name.String(), message);
@@ -517,12 +533,12 @@ PackageView::_InitProfiles()
for (i = 1; i < num; i++) { for (i = 1; i < num; i++) {
prof = fInfo.GetProfile(i); prof = fInfo.GetProfile(i);
if (prof) { if (prof) {
convert_size(prof->space_needed, sizeString, 32); convert_size(prof->space_needed, sizeString, 32);
name = prof->name; name = prof->name;
name << " (" << sizeString << ")"; name << " (" << sizeString << ")";
message = new BMessage(P_MSG_GROUP_CHANGED); message = new BMessage(P_MSG_GROUP_CHANGED);
message->AddInt32("index", i); message->AddInt32("index", i);
item = new BMenuItem(name.String(), message); item = new BMenuItem(name.String(), message);
@@ -534,6 +550,68 @@ 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. Should the "
"existing file be replaced with the one from this package?");
BAlert *alert = new BAlert(T("file_exists"), alertString.String(),
T("Yes"), T("No"), 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("Should this decision be remembered and all "
"existing files encountered in the future 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)
{ {
@@ -559,7 +637,7 @@ PackageView::_GroupChanged(int32 index)
BPath path; BPath path;
BMessage *temp; BMessage *temp;
BVolume volume; BVolume volume;
if (prof->path_type == P_INSTALL_PATH) { if (prof->path_type == P_INSTALL_PATH) {
dev_t device; dev_t device;
BString name; BString name;
@@ -570,7 +648,7 @@ PackageView::_GroupChanged(int32 index)
if (volume.SetTo(device) == B_OK && !volume.IsReadOnly()) { if (volume.SetTo(device) == B_OK && !volume.IsReadOnly()) {
temp = new BMessage(P_MSG_PATH_CHANGED); temp = new BMessage(P_MSG_PATH_CHANGED);
temp->AddString("path", BString(path.Path())); temp->AddString("path", BString(path.Path()));
convert_size(volume.FreeBytes(), sizeString, 32); convert_size(volume.FreeBytes(), sizeString, 32);
name = path.Path(); name = path.Path();
name << " (" << sizeString << " free)"; name << " (" << sizeString << " free)";
+4 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, Haiku, Inc. * Copyright 2007-2009, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Author: * Author:
@@ -36,12 +36,13 @@ class PackageView : public BView {
void AttachedToWindow(); void AttachedToWindow();
void MessageReceived(BMessage *msg); void MessageReceived(BMessage *msg);
status_t Install(); status_t Install();
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);
@@ -54,6 +55,7 @@ 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;