ext_attr.c revision c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4e
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 Public
10 * License.
11 * %End-Header%
12 */
13
14#include <stdio.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <string.h>
19#include <time.h>
20
21#include "ext2_fs.h"
22#include "ext2_ext_attr.h"
23
24#include "ext2fs.h"
25
26#ifdef EXT2FS_ENABLE_SWAPFS
27void ext2fs_swap_ext_attr(ext2_filsys fs, char *to, char *from)
28{
29	struct ext2_ext_attr_header *from_header =
30		(struct ext2_ext_attr_header *)from;
31	struct ext2_ext_attr_header *to_header =
32		(struct ext2_ext_attr_header *)to;
33	struct ext2_ext_attr_entry *from_entry, *to_entry;
34	char *from_end = (char *)from_header + fs->blocksize;
35	int n;
36
37	if (to_header != from_header)
38		memcpy(to_header, from_header, fs->blocksize);
39
40	to_header->h_magic    = ext2fs_swab32(from_header->h_magic);
41	to_header->h_blocks   = ext2fs_swab32(from_header->h_blocks);
42	to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
43	for (n=0; n<4; n++)
44		to_header->h_reserved[n] =
45			ext2fs_swab32(from_header->h_reserved[n]);
46
47	from_entry = (struct ext2_ext_attr_entry *)(from_header+1);
48	to_entry   = (struct ext2_ext_attr_entry *)(to_header+1);
49	while ((char *)from_entry < from_end && *(__u32 *)from_entry) {
50		to_entry->e_value_offs  =
51			ext2fs_swab16(from_entry->e_value_offs);
52		to_entry->e_value_block =
53			ext2fs_swab32(from_entry->e_value_block);
54		to_entry->e_value_size  =
55			ext2fs_swab32(from_entry->e_value_size);
56		from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
57		to_entry   = EXT2_EXT_ATTR_NEXT(to_entry);
58	}
59}
60#endif
61
62errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
63{
64	errcode_t	retval;
65
66 	retval = io_channel_read_blk(fs->io, block, 1, buf);
67	if (retval)
68		return retval;
69#ifdef EXT2FS_ENABLE_SWAPFS
70	if ((fs->flags & (EXT2_FLAG_SWAP_BYTES|
71			  EXT2_FLAG_SWAP_BYTES_READ)) != 0)
72		ext2fs_swap_ext_attr(fs, buf, buf);
73#endif
74	return 0;
75}
76
77errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
78{
79	errcode_t	retval;
80	char		*write_buf;
81	char		*buf = NULL;
82
83#ifdef EXT2FS_ENABLE_SWAPFS
84	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
85	    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) {
86		retval = ext2fs_get_mem(fs->blocksize, &buf);
87		if (retval)
88			return retval;
89		write_buf = buf;
90		ext2fs_swap_ext_attr(fs, buf, inbuf);
91	} else
92#endif
93		write_buf = (char *) inbuf;
94 	retval = io_channel_write_blk(fs->io, block, 1, write_buf);
95	if (buf)
96		ext2fs_free_mem(&buf);
97	if (!retval)
98		ext2fs_mark_changed(fs);
99	return retval;
100}
101
102/*
103 * This function adjusts the reference count of the EA block.
104 */
105errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
106				    char *block_buf, int adjust,
107				    __u32 *newcount)
108{
109	errcode_t	retval;
110	struct ext2_ext_attr_header *header;
111	char	*buf = 0;
112
113	if ((blk >= fs->super->s_blocks_count) ||
114	    (blk < fs->super->s_first_data_block))
115		return EXT2_ET_BAD_EA_BLOCK_NUM;
116
117	if (!block_buf) {
118		retval = ext2fs_get_mem(fs->blocksize, &buf);
119		if (retval)
120			return retval;
121		block_buf = buf;
122	}
123
124	retval = ext2fs_read_ext_attr(fs, blk, block_buf);
125	if (retval)
126		goto errout;
127
128	header = (struct ext2_ext_attr_header *) block_buf;
129	header->h_refcount += adjust;
130	if (newcount)
131		*newcount = header->h_refcount;
132
133	retval = ext2fs_write_ext_attr(fs, blk, block_buf);
134	if (retval)
135		goto errout;
136
137errout:
138	if (buf)
139		ext2fs_free_mem(&buf);
140	return retval;
141}
142