busybox/e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * irel_ma.c
   4 *
   5 * Copyright (C) 1996, 1997 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 <fcntl.h>
  14#include <stdio.h>
  15#include <string.h>
  16#if HAVE_UNISTD_H
  17#include <unistd.h>
  18#endif
  19#if HAVE_ERRNO_H
  20#include <errno.h>
  21#endif
  22
  23#include "ext2_fs.h"
  24#include "ext2fs.h"
  25#include "irel.h"
  26
  27static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
  28                         struct ext2_inode_relocate_entry *ent);
  29static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
  30                         struct ext2_inode_relocate_entry *ent);
  31static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
  32                                 struct ext2_inode_relocate_entry *ent);
  33static errcode_t ima_start_iter(ext2_irel irel);
  34static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
  35                          struct ext2_inode_relocate_entry *ent);
  36static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
  37                             struct ext2_inode_reference *ref);
  38static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino);
  39static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
  40static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new);
  41static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old);
  42static errcode_t ima_free(ext2_irel irel);
  43
  44/*
  45 * This data structure stores the array of inode references; there is
  46 * a structure for each inode.
  47 */
  48struct inode_reference_entry {
  49        __u16 num;
  50        struct ext2_inode_reference *refs;
  51};
  52
  53struct irel_ma {
  54        __u32 magic;
  55        ext2_ino_t max_inode;
  56        ext2_ino_t ref_current;
  57        int   ref_iter;
  58        ext2_ino_t      *orig_map;
  59        struct ext2_inode_relocate_entry *entries;
  60        struct inode_reference_entry *ref_entries;
  61};
  62
  63errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
  64                                      ext2_irel *new_irel)
  65{
  66        ext2_irel               irel = 0;
  67        errcode_t       retval;
  68        struct irel_ma  *ma = 0;
  69        size_t          size;
  70
  71        *new_irel = 0;
  72
  73        /*
  74         * Allocate memory structures
  75         */
  76        retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table),
  77                                &irel);
  78        if (retval)
  79                goto errout;
  80        memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
  81
  82        retval = ext2fs_get_mem(strlen(name)+1, &irel->name);
  83        if (retval)
  84                goto errout;
  85        strcpy(irel->name, name);
  86
  87        retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma);
  88        if (retval)
  89                goto errout;
  90        memset(ma, 0, sizeof(struct irel_ma));
  91        irel->priv_data = ma;
  92
  93        size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
  94        retval = ext2fs_get_mem(size, &ma->orig_map);
  95        if (retval)
  96                goto errout;
  97        memset(ma->orig_map, 0, size);
  98
  99        size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
 100                         (max_inode+1));
 101        retval = ext2fs_get_mem(size, &ma->entries);
 102        if (retval)
 103                goto errout;
 104        memset(ma->entries, 0, size);
 105
 106        size = (size_t) (sizeof(struct inode_reference_entry) *
 107                         (max_inode+1));
 108        retval = ext2fs_get_mem(size, &ma->ref_entries);
 109        if (retval)
 110                goto errout;
 111        memset(ma->ref_entries, 0, size);
 112        ma->max_inode = max_inode;
 113
 114        /*
 115         * Fill in the irel data structure
 116         */
 117        irel->put = ima_put;
 118        irel->get = ima_get;
 119        irel->get_by_orig = ima_get_by_orig;
 120        irel->start_iter = ima_start_iter;
 121        irel->next = ima_next;
 122        irel->add_ref = ima_add_ref;
 123        irel->start_iter_ref = ima_start_iter_ref;
 124        irel->next_ref = ima_next_ref;
 125        irel->move = ima_move;
 126        irel->delete = ima_delete;
 127        irel->free = ima_free;
 128
 129        *new_irel = irel;
 130        return 0;
 131
 132errout:
 133        ima_free(irel);
 134        return retval;
 135}
 136
 137static errcode_t ima_put(ext2_irel irel, ext2_ino_t old,
 138                        struct ext2_inode_relocate_entry *ent)
 139{
 140        struct inode_reference_entry    *ref_ent;
 141        struct irel_ma                  *ma;
 142        errcode_t                       retval;
 143        size_t                          size, old_size;
 144
 145        ma = irel->priv_data;
 146        if (old > ma->max_inode)
 147                return EXT2_ET_INVALID_ARGUMENT;
 148
 149        /*
 150         * Force the orig field to the correct value; the application
 151         * program shouldn't be messing with this field.
 152         */
 153        if (ma->entries[(unsigned) old].new == 0)
 154                ent->orig = old;
 155        else
 156                ent->orig = ma->entries[(unsigned) old].orig;
 157
 158        /*
 159         * If max_refs has changed, reallocate the refs array
 160         */
 161        ref_ent = ma->ref_entries + (unsigned) old;
 162        if (ref_ent->refs && ent->max_refs !=
 163            ma->entries[(unsigned) old].max_refs) {
 164                size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
 165                old_size = (sizeof(struct ext2_inode_reference) *
 166                            ma->entries[(unsigned) old].max_refs);
 167                retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs);
 168                if (retval)
 169                        return retval;
 170        }
 171
 172        ma->entries[(unsigned) old] = *ent;
 173        ma->orig_map[(unsigned) ent->orig] = old;
 174        return 0;
 175}
 176
 177static errcode_t ima_get(ext2_irel irel, ext2_ino_t old,
 178                        struct ext2_inode_relocate_entry *ent)
 179{
 180        struct irel_ma  *ma;
 181
 182        ma = irel->priv_data;
 183        if (old > ma->max_inode)
 184                return EXT2_ET_INVALID_ARGUMENT;
 185        if (ma->entries[(unsigned) old].new == 0)
 186                return ENOENT;
 187        *ent = ma->entries[(unsigned) old];
 188        return 0;
 189}
 190
 191static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old,
 192                        struct ext2_inode_relocate_entry *ent)
 193{
 194        struct irel_ma  *ma;
 195        ext2_ino_t      ino;
 196
 197        ma = irel->priv_data;
 198        if (orig > ma->max_inode)
 199                return EXT2_ET_INVALID_ARGUMENT;
 200        ino = ma->orig_map[(unsigned) orig];
 201        if (ino == 0)
 202                return ENOENT;
 203        *old = ino;
 204        *ent = ma->entries[(unsigned) ino];
 205        return 0;
 206}
 207
 208static errcode_t ima_start_iter(ext2_irel irel)
 209{
 210        irel->current = 0;
 211        return 0;
 212}
 213
 214static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old,
 215                         struct ext2_inode_relocate_entry *ent)
 216{
 217        struct irel_ma  *ma;
 218
 219        ma = irel->priv_data;
 220        while (++irel->current < ma->max_inode) {
 221                if (ma->entries[(unsigned) irel->current].new == 0)
 222                        continue;
 223                *old = irel->current;
 224                *ent = ma->entries[(unsigned) irel->current];
 225                return 0;
 226        }
 227        *old = 0;
 228        return 0;
 229}
 230
 231static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
 232                             struct ext2_inode_reference *ref)
 233{
 234        struct irel_ma  *ma;
 235        size_t          size;
 236        struct inode_reference_entry *ref_ent;
 237        struct ext2_inode_relocate_entry *ent;
 238        errcode_t               retval;
 239
 240        ma = irel->priv_data;
 241        if (ino > ma->max_inode)
 242                return EXT2_ET_INVALID_ARGUMENT;
 243
 244        ref_ent = ma->ref_entries + (unsigned) ino;
 245        ent = ma->entries + (unsigned) ino;
 246
 247        /*
 248         * If the inode reference array doesn't exist, create it.
 249         */
 250        if (ref_ent->refs == 0) {
 251                size = (size_t) ((sizeof(struct ext2_inode_reference) *
 252                                  ent->max_refs));
 253                retval = ext2fs_get_mem(size, &ref_ent->refs);
 254                if (retval)
 255                        return retval;
 256                memset(ref_ent->refs, 0, size);
 257                ref_ent->num = 0;
 258        }
 259
 260        if (ref_ent->num >= ent->max_refs)
 261                return EXT2_ET_TOO_MANY_REFS;
 262
 263        ref_ent->refs[(unsigned) ref_ent->num++] = *ref;
 264        return 0;
 265}
 266
 267static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino)
 268{
 269        struct irel_ma  *ma;
 270
 271        ma = irel->priv_data;
 272        if (ino > ma->max_inode)
 273                return EXT2_ET_INVALID_ARGUMENT;
 274        if (ma->entries[(unsigned) ino].new == 0)
 275                return ENOENT;
 276        ma->ref_current = ino;
 277        ma->ref_iter = 0;
 278        return 0;
 279}
 280
 281static errcode_t ima_next_ref(ext2_irel irel,
 282                              struct ext2_inode_reference *ref)
 283{
 284        struct irel_ma  *ma;
 285        struct inode_reference_entry *ref_ent;
 286
 287        ma = irel->priv_data;
 288
 289        ref_ent = ma->ref_entries + ma->ref_current;
 290
 291        if ((ref_ent->refs == NULL) ||
 292            (ma->ref_iter >= ref_ent->num)) {
 293                ref->block = 0;
 294                ref->offset = 0;
 295                return 0;
 296        }
 297        *ref = ref_ent->refs[ma->ref_iter++];
 298        return 0;
 299}
 300
 301
 302static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new)
 303{
 304        struct irel_ma  *ma;
 305
 306        ma = irel->priv_data;
 307        if ((old > ma->max_inode) || (new > ma->max_inode))
 308                return EXT2_ET_INVALID_ARGUMENT;
 309        if (ma->entries[(unsigned) old].new == 0)
 310                return ENOENT;
 311
 312        ma->entries[(unsigned) new] = ma->entries[(unsigned) old];
 313        ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs);
 314        ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old];
 315
 316        ma->entries[(unsigned) old].new = 0;
 317        ma->ref_entries[(unsigned) old].num = 0;
 318        ma->ref_entries[(unsigned) old].refs = 0;
 319
 320        ma->orig_map[ma->entries[new].orig] = new;
 321        return 0;
 322}
 323
 324static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old)
 325{
 326        struct irel_ma  *ma;
 327
 328        ma = irel->priv_data;
 329        if (old > ma->max_inode)
 330                return EXT2_ET_INVALID_ARGUMENT;
 331        if (ma->entries[(unsigned) old].new == 0)
 332                return ENOENT;
 333
 334        ma->entries[old].new = 0;
 335        ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs);
 336        ma->orig_map[ma->entries[(unsigned) old].orig] = 0;
 337
 338        ma->ref_entries[(unsigned) old].num = 0;
 339        ma->ref_entries[(unsigned) old].refs = 0;
 340        return 0;
 341}
 342
 343static errcode_t ima_free(ext2_irel irel)
 344{
 345        struct irel_ma  *ma;
 346        ext2_ino_t      ino;
 347
 348        if (!irel)
 349                return 0;
 350
 351        ma = irel->priv_data;
 352
 353        if (ma) {
 354                ext2fs_free_mem(&ma->orig_map);
 355                ext2fs_free_mem(&ma->entries);
 356                if (ma->ref_entries) {
 357                        for (ino = 0; ino <= ma->max_inode; ino++) {
 358                                ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs);
 359                        }
 360                        ext2fs_free_mem(&ma->ref_entries);
 361                }
 362                ext2fs_free_mem(&ma);
 363        }
 364        ext2fs_free_mem(&irel->name);
 365        ext2fs_free_mem(&irel);
 366        return 0;
 367}
 368