Whamcloud - gitweb
Shorten compile commands run by the build system
[tools/e2fsprogs.git] / lib / ext2fs / ext_attr.c
1 /*
2  * ext_attr.c --- extended attribute blocks
3  *
4  * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
5  *
6  * Copyright (C) 2002 Theodore Ts'o.
7  *
8  * %Begin-Header%
9  * This file may be redistributed under the terms of the GNU Library
10  * General Public License, version 2.
11  * %End-Header%
12  */
13
14 #include "config.h"
15 #include <stdio.h>
16 #if HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif
19 #include <string.h>
20 #include <time.h>
21
22 #include "ext2_fs.h"
23 #include "ext2_ext_attr.h"
24
25 #include "ext2fs.h"
26
27 #define NAME_HASH_SHIFT 5
28 #define VALUE_HASH_SHIFT 16
29
30 /*
31  * ext2_xattr_hash_entry()
32  *
33  * Compute the hash of an extended attribute.
34  */
35 __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
36 {
37         __u32 hash = 0;
38         char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry);
39         int n;
40
41         for (n = 0; n < entry->e_name_len; n++) {
42                 hash = (hash << NAME_HASH_SHIFT) ^
43                        (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
44                        *name++;
45         }
46
47         /* The hash needs to be calculated on the data in little-endian. */
48         if (entry->e_value_block == 0 && entry->e_value_size != 0) {
49                 __u32 *value = (__u32 *)data;
50                 for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
51                          EXT2_EXT_ATTR_PAD_BITS; n; n--) {
52                         hash = (hash << VALUE_HASH_SHIFT) ^
53                                (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
54                                ext2fs_le32_to_cpu(*value++);
55                 }
56         }
57
58         return hash;
59 }
60
61 #undef NAME_HASH_SHIFT
62 #undef VALUE_HASH_SHIFT
63
64 errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf)
65 {
66         errcode_t       retval;
67
68         retval = io_channel_read_blk64(fs->io, block, 1, buf);
69         if (retval)
70                 return retval;
71 #ifdef WORDS_BIGENDIAN
72         ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
73 #endif
74         return 0;
75 }
76
77 errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
78 {
79         return ext2fs_read_ext_attr2(fs, block, buf);
80 }
81
82 errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf)
83 {
84         errcode_t       retval;
85         char            *write_buf;
86 #ifdef WORDS_BIGENDIAN
87         char            *buf = NULL;
88
89         retval = ext2fs_get_mem(fs->blocksize, &buf);
90         if (retval)
91                 return retval;
92         write_buf = buf;
93         ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1);
94 #else
95         write_buf = (char *) inbuf;
96 #endif
97         retval = io_channel_write_blk64(fs->io, block, 1, write_buf);
98 #ifdef WORDS_BIGENDIAN
99         ext2fs_free_mem(&buf);
100 #endif
101         if (!retval)
102                 ext2fs_mark_changed(fs);
103         return retval;
104 }
105
106 errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
107 {
108         return ext2fs_write_ext_attr2(fs, block, inbuf);
109 }
110
111 /*
112  * This function adjusts the reference count of the EA block.
113  */
114 errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
115                                     char *block_buf, int adjust,
116                                     __u32 *newcount)
117 {
118         errcode_t       retval;
119         struct ext2_ext_attr_header *header;
120         char    *buf = 0;
121
122         if ((blk >= ext2fs_blocks_count(fs->super)) ||
123             (blk < fs->super->s_first_data_block))
124                 return EXT2_ET_BAD_EA_BLOCK_NUM;
125
126         if (!block_buf) {
127                 retval = ext2fs_get_mem(fs->blocksize, &buf);
128                 if (retval)
129                         return retval;
130                 block_buf = buf;
131         }
132
133         retval = ext2fs_read_ext_attr2(fs, blk, block_buf);
134         if (retval)
135                 goto errout;
136
137         header = (struct ext2_ext_attr_header *) block_buf;
138         header->h_refcount += adjust;
139         if (newcount)
140                 *newcount = header->h_refcount;
141
142         retval = ext2fs_write_ext_attr2(fs, blk, block_buf);
143         if (retval)
144                 goto errout;
145
146 errout:
147         if (buf)
148                 ext2fs_free_mem(&buf);
149         return retval;
150 }
151
152 errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
153                                         char *block_buf, int adjust,
154                                         __u32 *newcount)
155 {
156         return ext2fs_adjust_ea_refcount(fs, blk, block_buf, adjust, newcount);
157 }