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