haiku/src/tools/generate_attribute_stores.cpp
Michael Lotz c26b324e20 Should fix GCC4 build.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30853 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-05-25 21:26:54 +00:00

154 lines
3.4 KiB
C++

/*
* 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 <string.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;
}