2 * Copyright 2009, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
15 #include <Directory.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'
33 struct attribute_entry
{
36 uint8 name_length
; // including 0 byte
37 char name
[1]; // 0 terminated, followed by data
42 recurse_directory(BDirectory
&directory
, uint8
*copyBuffer
)
46 BDirectory attributeDir
;
47 bool attributeDirCreated
= false;
48 char nameBuffer
[B_FILE_NAME_LENGTH
];
51 while (directory
.GetNextRef(&ref
) == B_OK
) {
52 if (strcmp(ref
.name
, ATTRIBUTE_DIR_NAME
) == 0)
55 if (node
.SetTo(&ref
) != B_OK
) {
56 printf("failed to set node to ref \"%s\"\n", ref
.name
);
62 uint32 attributeCount
= 0;
63 while (node
.GetNextAttrName(nameBuffer
) == B_OK
) {
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
);
71 if (attributeCount
== 0) {
72 if (!attributeDirCreated
) {
73 directory
.CreateDirectory(ATTRIBUTE_DIR_NAME
, NULL
);
74 if (!directory
.Contains(ATTRIBUTE_DIR_NAME
,
76 printf("attribute store directory not available\n");
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");
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
);
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
,
106 printf("error reading attribute \"%s\" of file \"%s\"\n",
107 nameBuffer
, ref
.name
);
111 attributeFile
.Write(copyBuffer
, copySize
);
112 info
.size
-= COPY_BUFFER_SIZE
;
113 offset
+= COPY_BUFFER_SIZE
;
119 if (attributeCount
> 0) {
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
[])
138 printf("usage: %s <root directory>\n", argv
[0]);
142 uint8
*copyBuffer
= (uint8
*)malloc(COPY_BUFFER_SIZE
);
143 if (copyBuffer
== NULL
) {
144 printf("cannot allocate copy buffer\n");
148 BDirectory
root(argv
[1]);
149 recurse_directory(root
, copyBuffer
);