Add a generate_attribute_stores build tool. It can be used to recursively
generate attribute stores for attribute overlay. This can be used to generate ISO only Haiku CDs with attribute support in the future. Note that while they are mostly bootable they aren't really usable yet because of the missing query support. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29194 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a079780e8a
commit
cbaec88839
@ -39,6 +39,9 @@ BuildPlatformMain <build>copyattr : copyattr.cpp
|
||||
BuildPlatformMain <build>data_to_source : data_to_source.cpp
|
||||
: $(HOST_LIBSUPC++) ;
|
||||
|
||||
BuildPlatformMain <build>generate_attribute_stores
|
||||
: generate_attribute_stores.cpp : $(HOST_LIBBE) ;
|
||||
|
||||
UsePrivateObjectHeaders generate_boot_screen.cpp : shared : : true ;
|
||||
UsePrivateObjectHeaders ColorQuantizer.cpp : shared : : true ;
|
||||
BuildPlatformMain <build>generate_boot_screen :
|
||||
|
152
src/tools/generate_attribute_stores.cpp
Normal file
152
src/tools/generate_attribute_stores.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs_attr.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <Node.h>
|
||||
|
||||
|
||||
#define ATTRIBUTE_FILE_MAGIC 'attr'
|
||||
#define ATTRIBUTE_DIR_NAME "_HAIKU"
|
||||
#define COPY_BUFFER_SIZE 128 * 1024
|
||||
|
||||
|
||||
struct attribute_file {
|
||||
uint32 magic; // 'attr'
|
||||
uint32 entry_count;
|
||||
uint8 entries[1];
|
||||
} _PACKED;
|
||||
|
||||
|
||||
struct attribute_entry {
|
||||
type_code type;
|
||||
uint32 size;
|
||||
uint8 name_length; // including 0 byte
|
||||
char name[1]; // 0 terminated, followed by data
|
||||
} _PACKED;
|
||||
|
||||
|
||||
void
|
||||
recurse_directory(BDirectory &directory, uint8 *copyBuffer)
|
||||
{
|
||||
BNode node;
|
||||
entry_ref ref;
|
||||
BDirectory attributeDir;
|
||||
bool attributeDirCreated = false;
|
||||
char nameBuffer[B_FILE_NAME_LENGTH];
|
||||
directory.Rewind();
|
||||
|
||||
while (directory.GetNextRef(&ref) == B_OK) {
|
||||
if (strcmp(ref.name, ATTRIBUTE_DIR_NAME) == 0)
|
||||
continue;
|
||||
|
||||
if (node.SetTo(&ref) != B_OK) {
|
||||
printf("failed to set node to ref \"%s\"\n", ref.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
node.RewindAttrs();
|
||||
BFile attributeFile;
|
||||
uint32 attributeCount = 0;
|
||||
while (node.GetNextAttrName(nameBuffer) == B_OK) {
|
||||
attr_info info;
|
||||
if (node.GetAttrInfo(nameBuffer, &info) != B_OK) {
|
||||
printf("failed to get attr info of \"%s\" on file \"%s\"\n",
|
||||
nameBuffer, ref.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attributeCount == 0) {
|
||||
if (!attributeDirCreated) {
|
||||
directory.CreateDirectory(ATTRIBUTE_DIR_NAME, NULL);
|
||||
if (!directory.Contains(ATTRIBUTE_DIR_NAME,
|
||||
B_DIRECTORY_NODE)) {
|
||||
printf("attribute store directory not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
attributeDir.SetTo(&directory, ATTRIBUTE_DIR_NAME);
|
||||
attributeDirCreated = true;
|
||||
}
|
||||
|
||||
attributeDir.CreateFile(ref.name, NULL);
|
||||
if (attributeFile.SetTo(&attributeDir, ref.name,
|
||||
B_WRITE_ONLY | B_ERASE_FILE) != B_OK) {
|
||||
printf("cannot open attribute file for writing\n");
|
||||
break;
|
||||
}
|
||||
|
||||
attributeFile.Seek(sizeof(attribute_file) - 1, SEEK_SET);
|
||||
}
|
||||
|
||||
attribute_entry entry;
|
||||
entry.type = info.type;
|
||||
entry.size = info.size;
|
||||
entry.name_length = strlen(nameBuffer) + 1;
|
||||
attributeFile.Write(&entry, sizeof(attribute_entry) - 1);
|
||||
attributeFile.Write(nameBuffer, entry.name_length);
|
||||
|
||||
off_t offset = 0;
|
||||
while (info.size > 0) {
|
||||
size_t copySize = min_c(info.size, COPY_BUFFER_SIZE);
|
||||
if (node.ReadAttr(nameBuffer, info.type, offset, copyBuffer,
|
||||
copySize) < B_OK) {
|
||||
printf("error reading attribute \"%s\" of file \"%s\"\n",
|
||||
nameBuffer, ref.name);
|
||||
return;
|
||||
}
|
||||
|
||||
attributeFile.Write(copyBuffer, copySize);
|
||||
info.size -= COPY_BUFFER_SIZE;
|
||||
offset += COPY_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
attributeCount++;
|
||||
}
|
||||
|
||||
if (attributeCount > 0) {
|
||||
attribute_file file;
|
||||
file.magic = ATTRIBUTE_FILE_MAGIC;
|
||||
file.entry_count = attributeCount;
|
||||
attributeFile.WriteAt(0, &file, sizeof(attribute_file) - 1);
|
||||
}
|
||||
|
||||
if (node.IsDirectory()) {
|
||||
BDirectory subDirectory(&ref);
|
||||
recurse_directory(subDirectory, copyBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: %s <root directory>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8 *copyBuffer = (uint8 *)malloc(COPY_BUFFER_SIZE);
|
||||
if (copyBuffer == NULL) {
|
||||
printf("cannot allocate copy buffer\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
BDirectory root(argv[1]);
|
||||
recurse_directory(root, copyBuffer);
|
||||
|
||||
free(copyBuffer);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user