libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / tools / generate_attribute_stores.cpp
blob056bb874cd6d3da0f39ed7bf3f8faffe4b8b759a
1 /*
2 * Copyright 2009, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include <fs_attr.h>
15 #include <Directory.h>
16 #include <Entry.h>
17 #include <File.h>
18 #include <Node.h>
21 #define ATTRIBUTE_FILE_MAGIC 'attr'
22 #define ATTRIBUTE_DIR_NAME "_HAIKU"
23 #define COPY_BUFFER_SIZE 128 * 1024
26 struct attribute_file {
27 uint32 magic; // 'attr'
28 uint32 entry_count;
29 uint8 entries[1];
30 } _PACKED;
33 struct attribute_entry {
34 type_code type;
35 uint32 size;
36 uint8 name_length; // including 0 byte
37 char name[1]; // 0 terminated, followed by data
38 } _PACKED;
41 void
42 recurse_directory(BDirectory &directory, uint8 *copyBuffer)
44 BNode node;
45 entry_ref ref;
46 BDirectory attributeDir;
47 bool attributeDirCreated = false;
48 char nameBuffer[B_FILE_NAME_LENGTH];
49 directory.Rewind();
51 while (directory.GetNextRef(&ref) == B_OK) {
52 if (strcmp(ref.name, ATTRIBUTE_DIR_NAME) == 0)
53 continue;
55 if (node.SetTo(&ref) != B_OK) {
56 printf("failed to set node to ref \"%s\"\n", ref.name);
57 continue;
60 node.RewindAttrs();
61 BFile attributeFile;
62 uint32 attributeCount = 0;
63 while (node.GetNextAttrName(nameBuffer) == B_OK) {
64 attr_info info;
65 if (node.GetAttrInfo(nameBuffer, &info) != B_OK) {
66 printf("failed to get attr info of \"%s\" on file \"%s\"\n",
67 nameBuffer, ref.name);
68 continue;
71 if (attributeCount == 0) {
72 if (!attributeDirCreated) {
73 directory.CreateDirectory(ATTRIBUTE_DIR_NAME, NULL);
74 if (!directory.Contains(ATTRIBUTE_DIR_NAME,
75 B_DIRECTORY_NODE)) {
76 printf("attribute store directory not available\n");
77 return;
80 attributeDir.SetTo(&directory, ATTRIBUTE_DIR_NAME);
81 attributeDirCreated = true;
84 attributeDir.CreateFile(ref.name, NULL);
85 if (attributeFile.SetTo(&attributeDir, ref.name,
86 B_WRITE_ONLY | B_ERASE_FILE) != B_OK) {
87 printf("cannot open attribute file for writing\n");
88 break;
91 attributeFile.Seek(sizeof(attribute_file) - 1, SEEK_SET);
94 attribute_entry entry;
95 entry.type = info.type;
96 entry.size = info.size;
97 entry.name_length = strlen(nameBuffer) + 1;
98 attributeFile.Write(&entry, sizeof(attribute_entry) - 1);
99 attributeFile.Write(nameBuffer, entry.name_length);
101 off_t offset = 0;
102 while (info.size > 0) {
103 size_t copySize = min_c(info.size, COPY_BUFFER_SIZE);
104 if (node.ReadAttr(nameBuffer, info.type, offset, copyBuffer,
105 copySize) < B_OK) {
106 printf("error reading attribute \"%s\" of file \"%s\"\n",
107 nameBuffer, ref.name);
108 return;
111 attributeFile.Write(copyBuffer, copySize);
112 info.size -= COPY_BUFFER_SIZE;
113 offset += COPY_BUFFER_SIZE;
116 attributeCount++;
119 if (attributeCount > 0) {
120 attribute_file file;
121 file.magic = ATTRIBUTE_FILE_MAGIC;
122 file.entry_count = attributeCount;
123 attributeFile.WriteAt(0, &file, sizeof(attribute_file) - 1);
126 if (node.IsDirectory()) {
127 BDirectory subDirectory(&ref);
128 recurse_directory(subDirectory, copyBuffer);
135 main(int argc, char *argv[])
137 if (argc < 2) {
138 printf("usage: %s <root directory>\n", argv[0]);
139 return 1;
142 uint8 *copyBuffer = (uint8 *)malloc(COPY_BUFFER_SIZE);
143 if (copyBuffer == NULL) {
144 printf("cannot allocate copy buffer\n");
145 return 2;
148 BDirectory root(argv[1]);
149 recurse_directory(root, copyBuffer);
151 free(copyBuffer);
152 return 0;