busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * dirblock.c --- directory block routines.
   4 *
   5 * Copyright (C) 1995, 1996 Theodore Ts'o.
   6 *
   7 * %Begin-Header%
   8 * This file may be redistributed under the terms of the GNU Public
   9 * License.
  10 * %End-Header%
  11 */
  12
  13#include <stdio.h>
  14#if HAVE_UNISTD_H
  15#include <unistd.h>
  16#endif
  17#include <string.h>
  18#include <time.h>
  19
  20#include "ext2_fs.h"
  21#include "ext2fs.h"
  22
  23errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
  24                                 void *buf, int flags EXT2FS_ATTR((unused)))
  25{
  26        errcode_t       retval;
  27        char            *p, *end;
  28        struct ext2_dir_entry *dirent;
  29        unsigned int    name_len, rec_len;
  30#if BB_BIG_ENDIAN
  31        unsigned int do_swap;
  32#endif
  33
  34        retval = io_channel_read_blk(fs->io, block, 1, buf);
  35        if (retval)
  36                return retval;
  37#if BB_BIG_ENDIAN
  38        do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
  39                                EXT2_FLAG_SWAP_BYTES_READ)) != 0;
  40#endif
  41        p = (char *) buf;
  42        end = (char *) buf + fs->blocksize;
  43        while (p < end-8) {
  44                dirent = (struct ext2_dir_entry *) p;
  45#if BB_BIG_ENDIAN
  46                if (do_swap) {
  47                        dirent->inode = ext2fs_swab32(dirent->inode);
  48                        dirent->rec_len = ext2fs_swab16(dirent->rec_len);
  49                        dirent->name_len = ext2fs_swab16(dirent->name_len);
  50                }
  51#endif
  52                name_len = dirent->name_len;
  53#ifdef WORDS_BIGENDIAN
  54                if (flags & EXT2_DIRBLOCK_V2_STRUCT)
  55                        dirent->name_len = ext2fs_swab16(dirent->name_len);
  56#endif
  57                rec_len = dirent->rec_len;
  58                if ((rec_len < 8) || (rec_len % 4)) {
  59                        rec_len = 8;
  60                        retval = EXT2_ET_DIR_CORRUPTED;
  61                }
  62                if (((name_len & 0xFF) + 8) > dirent->rec_len)
  63                        retval = EXT2_ET_DIR_CORRUPTED;
  64                p += rec_len;
  65        }
  66        return retval;
  67}
  68
  69errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
  70                                 void *buf)
  71{
  72        return ext2fs_read_dir_block2(fs, block, buf, 0);
  73}
  74
  75
  76errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
  77                                  void *inbuf, int flags EXT2FS_ATTR((unused)))
  78{
  79#if BB_BIG_ENDIAN
  80        int             do_swap = 0;
  81        errcode_t       retval;
  82        char            *p, *end;
  83        char            *buf = NULL;
  84        struct ext2_dir_entry *dirent;
  85
  86        if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  87            (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
  88                do_swap = 1;
  89
  90#ifndef WORDS_BIGENDIAN
  91        if (!do_swap)
  92                return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
  93#endif
  94
  95        retval = ext2fs_get_mem(fs->blocksize, &buf);
  96        if (retval)
  97                return retval;
  98        memcpy(buf, inbuf, fs->blocksize);
  99        p = buf;
 100        end = buf + fs->blocksize;
 101        while (p < end) {
 102                dirent = (struct ext2_dir_entry *) p;
 103                if ((dirent->rec_len < 8) ||
 104                    (dirent->rec_len % 4)) {
 105                        ext2fs_free_mem(&buf);
 106                        return EXT2_ET_DIR_CORRUPTED;
 107                }
 108                p += dirent->rec_len;
 109                if (do_swap) {
 110                        dirent->inode = ext2fs_swab32(dirent->inode);
 111                        dirent->rec_len = ext2fs_swab16(dirent->rec_len);
 112                        dirent->name_len = ext2fs_swab16(dirent->name_len);
 113                }
 114#ifdef WORDS_BIGENDIAN
 115                if (flags & EXT2_DIRBLOCK_V2_STRUCT)
 116                        dirent->name_len = ext2fs_swab16(dirent->name_len);
 117#endif
 118        }
 119        retval = io_channel_write_blk(fs->io, block, 1, buf);
 120        ext2fs_free_mem(&buf);
 121        return retval;
 122#else
 123        return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
 124#endif
 125}
 126
 127
 128errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
 129                                 void *inbuf)
 130{
 131        return ext2fs_write_dir_block2(fs, block, inbuf, 0);
 132}
 133