~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grub4dos/stage2/.svn/text-base/fsys_ufs2.c.svn-base

  • Committer: Howard Chan
  • Date: 2012-11-20 10:16:05 UTC
  • Revision ID: smartboyhw@gmail.com-20121120101605-qfmjfsdynpzg9an9
Added images

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