From cbaec88839d80a10294c3330519b6efd918ddd8e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 14 Feb 2009 00:28:35 +0000 Subject: [PATCH] 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 --- src/tools/Jamfile | 3 + src/tools/generate_attribute_stores.cpp | 152 ++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 src/tools/generate_attribute_stores.cpp diff --git a/src/tools/Jamfile b/src/tools/Jamfile index dbe3a54097..1daa7179e3 100644 --- a/src/tools/Jamfile +++ b/src/tools/Jamfile @@ -39,6 +39,9 @@ BuildPlatformMain copyattr : copyattr.cpp BuildPlatformMain data_to_source : data_to_source.cpp : $(HOST_LIBSUPC++) ; +BuildPlatformMain generate_attribute_stores + : generate_attribute_stores.cpp : $(HOST_LIBBE) ; + UsePrivateObjectHeaders generate_boot_screen.cpp : shared : : true ; UsePrivateObjectHeaders ColorQuantizer.cpp : shared : : true ; BuildPlatformMain generate_boot_screen : diff --git a/src/tools/generate_attribute_stores.cpp b/src/tools/generate_attribute_stores.cpp new file mode 100644 index 0000000000..c679134c7b --- /dev/null +++ b/src/tools/generate_attribute_stores.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2009, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +#include +#include + +#include + +#include +#include +#include +#include + + +#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 \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; +}