~ubuntu-branches/ubuntu/utopic/grub/utopic

« back to all changes in this revision

Viewing changes to stage2/fsys_ffs.c

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2002-02-04 15:35:01 UTC
  • Revision ID: james.westby@ubuntu.com-20020204153501-neulkag77r3a2m0v
Tags: upstream-0.91
ImportĀ upstreamĀ versionĀ 0.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
 */
 
19
 
 
20
/*
 
21
 * Elements of this file were originally from the FreeBSD "biosboot"
 
22
 * bootloader file "disk.c" dated 4/12/95.
 
23
 *
 
24
 * The license and header comments from that file are included here.
 
25
 */
 
26
 
 
27
/*
 
28
 * Mach Operating System
 
29
 * Copyright (c) 1992, 1991 Carnegie Mellon University
 
30
 * All Rights Reserved.
 
31
 *
 
32
 * Permission to use, copy, modify and distribute this software and its
 
33
 * documentation is hereby granted, provided that both the copyright
 
34
 * notice and this permission notice appear in all copies of the
 
35
 * software, derivative works or modified versions, and any portions
 
36
 * thereof, and that both notices appear in supporting documentation.
 
37
 *
 
38
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 
39
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 
40
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 
41
 *
 
42
 * Carnegie Mellon requests users of this software to return to
 
43
 *
 
44
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 
45
 *  School of Computer Science
 
46
 *  Carnegie Mellon University
 
47
 *  Pittsburgh PA 15213-3890
 
48
 *
 
49
 * any improvements or extensions that they make and grant Carnegie Mellon
 
50
 * the rights to redistribute these changes.
 
51
 *
 
52
 *      from: Mach, Revision 2.2  92/04/04  11:35:49  rpd
 
53
 *      $Id: fsys_ffs.c,v 1.10 2001/11/12 06:57:29 okuji Exp $
 
54
 */
 
55
 
 
56
#ifdef FSYS_FFS
 
57
 
 
58
#include "shared.h"
 
59
 
 
60
#include "filesys.h"
 
61
 
 
62
#include "defs.h"
 
63
#include "disk_inode.h"
 
64
#include "disk_inode_ffs.h"
 
65
#include "dir.h"
 
66
#include "fs.h"
 
67
 
 
68
/* used for filesystem map blocks */
 
69
static int mapblock;
 
70
static int mapblock_offset;
 
71
static int mapblock_bsize;
 
72
 
 
73
/* pointer to superblock */
 
74
#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 ))
 
75
#define INODE ((struct icommon *) ( FSYS_BUF + 16384 ))
 
76
#define MAPBUF ( FSYS_BUF + 24576 )
 
77
#define MAPBUF_LEN 8192
 
78
 
 
79
 
 
80
int
 
81
ffs_mount (void)
 
82
{
 
83
  int retval = 1;
 
84
 
 
85
  if ((((current_drive & 0x80) || (current_slice != 0))
 
86
       && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))
 
87
      || part_length < (SBLOCK + (SBSIZE / DEV_BSIZE))
 
88
      || !devread (SBLOCK, 0, SBSIZE, (char *) SUPERBLOCK)
 
89
      || SUPERBLOCK->fs_magic != FS_MAGIC)
 
90
    retval = 0;
 
91
 
 
92
  mapblock = -1;
 
93
  mapblock_offset = -1;
 
94
  
 
95
  return retval;
 
96
}
 
97
 
 
98
static int
 
99
block_map (int file_block)
 
100
{
 
101
  int bnum, offset, bsize;
 
102
  
 
103
  if (file_block < NDADDR)
 
104
    return (INODE->i_db[file_block]);
 
105
  
 
106
  /* If the blockmap loaded does not include FILE_BLOCK,
 
107
     load a new blockmap.  */
 
108
  if ((bnum = fsbtodb (SUPERBLOCK, INODE->i_ib[0])) != mapblock
 
109
      || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize))
 
110
    {
 
111
      if (MAPBUF_LEN < SUPERBLOCK->fs_bsize)
 
112
        {
 
113
          offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK));
 
114
          bsize = MAPBUF_LEN;
 
115
          
 
116
          if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize)
 
117
            offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int);
 
118
        }
 
119
      else
 
120
        {
 
121
          bsize = SUPERBLOCK->fs_bsize;
 
122
          offset = 0;
 
123
        }
 
124
      
 
125
      if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF))
 
126
        {
 
127
          mapblock = -1;
 
128
          mapblock_bsize = -1;
 
129
          mapblock_offset = -1;
 
130
          errnum = ERR_FSYS_CORRUPT;
 
131
          return -1;
 
132
        }
 
133
      
 
134
      mapblock = bnum;
 
135
      mapblock_bsize = bsize;
 
136
      mapblock_offset = offset;
 
137
    }
 
138
  
 
139
  return (((int *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK))
 
140
                          - mapblock_offset]);
 
141
}
 
142
 
 
143
 
 
144
int
 
145
ffs_read (char *buf, int len)
 
146
{
 
147
  int logno, off, size, map, ret = 0;
 
148
  
 
149
  while (len && !errnum)
 
150
    {
 
151
      off = blkoff (SUPERBLOCK, filepos);
 
152
      logno = lblkno (SUPERBLOCK, filepos);
 
153
      size = blksize (SUPERBLOCK, INODE, logno);
 
154
 
 
155
      if ((map = block_map (logno)) < 0)
 
156
        break;
 
157
 
 
158
      size -= off;
 
159
 
 
160
      if (size > len)
 
161
        size = len;
 
162
 
 
163
      disk_read_func = disk_read_hook;
 
164
 
 
165
      devread (fsbtodb (SUPERBLOCK, map), off, size, buf);
 
166
 
 
167
      disk_read_func = NULL;
 
168
 
 
169
      buf += size;
 
170
      len -= size;
 
171
      filepos += size;
 
172
      ret += size;
 
173
    }
 
174
 
 
175
  if (errnum)
 
176
    ret = 0;
 
177
 
 
178
  return ret;
 
179
}
 
180
 
 
181
 
 
182
int
 
183
ffs_dir (char *dirname)
 
184
{
 
185
  char *rest, ch;
 
186
  int block, off, loc, map, ino = ROOTINO;
 
187
  struct direct *dp;
 
188
 
 
189
/* main loop to find destination inode */
 
190
loop:
 
191
 
 
192
  /* load current inode (defaults to the root inode) */
 
193
 
 
194
        if (!devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)),
 
195
                                                                ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode),
 
196
                                                                sizeof (struct dinode), (char *) INODE))
 
197
                        return 0;                       /* XXX what return value? */
 
198
 
 
199
  /* if we have a real file (and we're not just printing possibilities),
 
200
     then this is where we want to exit */
 
201
 
 
202
  if (!*dirname || isspace (*dirname))
 
203
    {
 
204
      if ((INODE->i_mode & IFMT) != IFREG)
 
205
        {
 
206
          errnum = ERR_BAD_FILETYPE;
 
207
          return 0;
 
208
        }
 
209
 
 
210
      filemax = INODE->i_size;
 
211
 
 
212
      /* incomplete implementation requires this! */
 
213
      fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize;
 
214
      return 1;
 
215
    }
 
216
 
 
217
  /* continue with file/directory name interpretation */
 
218
 
 
219
  while (*dirname == '/')
 
220
    dirname++;
 
221
 
 
222
  if (!(INODE->i_size) || ((INODE->i_mode & IFMT) != IFDIR))
 
223
    {
 
224
      errnum = ERR_BAD_FILETYPE;
 
225
      return 0;
 
226
    }
 
227
 
 
228
  for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
 
229
 
 
230
  *rest = 0;
 
231
  loc = 0;
 
232
 
 
233
  /* loop for reading a the entries in a directory */
 
234
 
 
235
  do
 
236
    {
 
237
      if (loc >= INODE->i_size)
 
238
        {
 
239
#if 0
 
240
          putchar ('\n');
 
241
#endif
 
242
 
 
243
          if (print_possibilities < 0)
 
244
            return 1;
 
245
 
 
246
          errnum = ERR_FILE_NOT_FOUND;
 
247
          *rest = ch;
 
248
          return 0;
 
249
        }
 
250
 
 
251
      if (!(off = blkoff (SUPERBLOCK, loc)))
 
252
        {
 
253
          block = lblkno (SUPERBLOCK, loc);
 
254
 
 
255
          if ((map = block_map (block)) < 0
 
256
              || !devread (fsbtodb (SUPERBLOCK, map), 0,
 
257
                           blksize (SUPERBLOCK, INODE, block),
 
258
                           (char *) FSYS_BUF))
 
259
            {
 
260
              errnum = ERR_FSYS_CORRUPT;
 
261
              *rest = ch;
 
262
              return 0;
 
263
            }
 
264
        }
 
265
 
 
266
      dp = (struct direct *) (FSYS_BUF + off);
 
267
      loc += dp->d_reclen;
 
268
 
 
269
#ifndef STAGE1_5
 
270
      if (dp->d_ino && print_possibilities && ch != '/'
 
271
          && (!*dirname || substring (dirname, dp->d_name) <= 0))
 
272
        {
 
273
          if (print_possibilities > 0)
 
274
            print_possibilities = -print_possibilities;
 
275
 
 
276
          print_a_completion (dp->d_name);
 
277
        }
 
278
#endif /* STAGE1_5 */
 
279
    }
 
280
  while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
 
281
                        || (print_possibilities && ch != '/')));
 
282
 
 
283
  /* only get here if we have a matching directory entry */
 
284
 
 
285
  ino = dp->d_ino;
 
286
  *(dirname = rest) = ch;
 
287
 
 
288
  /* go back to main loop at top of function */
 
289
  goto loop;
 
290
}
 
291
 
 
292
int
 
293
ffs_embed (int *start_sector, int needed_sectors)
 
294
{
 
295
  /* XXX: I don't know if this is really correct. Someone who is
 
296
     familiar with BSD should check for this.  */
 
297
  if (needed_sectors > 14)
 
298
    return 0;
 
299
  
 
300
  *start_sector = 1;
 
301
#if 1
 
302
  /* FIXME: Disable the embedding in FFS until someone checks if
 
303
     the code above is correct.  */
 
304
  return 0;
 
305
#else
 
306
  return 1;
 
307
#endif
 
308
}
 
309
 
 
310
#endif /* FSYS_FFS */