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:
Michael Lotz 2009-02-14 00:28:35 +00:00
parent a079780e8a
commit cbaec88839
2 changed files with 155 additions and 0 deletions

View File

@ -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 :

View 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;
}