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