Files
xen/tools/libfsimage/ufs/fsys_ufs.c
T
Ian Campbell 443701ef0c Replace FSF street address with canonical URL
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html.

This is the result of:
$ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl

Where fsf.pl is:
    #!/usr/bin/perl -w -pi.bak -0777
    my $repl = 'If not, see <http://www.gnu.org/licenses/>.';
    my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/;

    my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/;

    my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/;
    my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/;
    my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/;

    s|$inwt$br$mass|$repl|m;
    s|$inwt$br$franklin|$repl|m;
    s|$inwt$br$temple|$repl|m;

The only remaining mentions of these addresses are in COPYING files which I
haven't touched.

Some of the changed files are imports from elsewhere, however
filtering them out is tricky, I think it is tolerable to have these
files be modified here and then perhaps reverted on the next sync,
since it's only 1-2 lines and obvious what is going on.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
2015-07-29 11:14:07 +01:00

278 lines
6.7 KiB
C

/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* From Solaris usr/src/stand/lib/fs/ufs/ufsops.c */
#include <fsimage_grub.h>
#include "ufs.h"
/* These are the pools of buffers, etc. */
#define SUPERBLOCK ((struct fs *)(FSYS_BUF + 0x2000))
#define INODE ((struct icommon *)(FSYS_BUF + 0x1000))
#define DIRENT (FSYS_BUF + 0x4000)
#define MAXBSIZE ((FSYS_BUFLEN - 0x4000) / 2)
#define INDIRBLK1 ((grub_daddr32_t *)(FSYS_BUF + 0x4000)) /* 2+ indir blk */
#define INDIRBLK0 ((grub_daddr32_t *)(FSYS_BUF+ 0x4000 + MAXBSIZE)) /* 1st indirect blk */
#define indirblk0 (*fsig_int1(ffi))
#define indirblk1 (*fsig_int2(ffi))
static int openi(fsi_file_t *, grub_ino_t);
static grub_ino_t dlook(fsi_file_t *, grub_ino_t, char *);
static grub_daddr32_t sbmap(fsi_file_t *, grub_daddr32_t);
/* read superblock and check fs magic */
static int
ufs_mount(fsi_file_t *ffi, const char *options)
{
if (/*! IS_PC_SLICE_TYPE_SOLARIS(current_slice) || */
!devread(ffi, UFS_SBLOCK, 0, UFS_SBSIZE, (char *)SUPERBLOCK) ||
SUPERBLOCK->fs_magic != UFS_MAGIC ||
MAXBSIZE < SUPERBLOCK->fs_bsize)
return 0;
return 1;
}
/*
* searching for a file, if successful, inode will be loaded in INODE
* The entry point should really be named ufs_open(char *pathname).
* For now, keep it consistent with the rest of fsys modules.
*/
static int
ufs_dir(fsi_file_t *ffi, char *dirname)
{
grub_ino_t inode = ROOTINO; /* start from root */
char *fname, ch;
indirblk0 = indirblk1 = 0;
/* skip leading slashes */
while (*dirname == '/')
dirname++;
while (inode && *dirname && !isspace((uint8_t)*dirname)) {
if (!openi(ffi, inode))
return 0;
/* parse for next path component */
fname = dirname;
while (*dirname && !isspace((uint8_t)*dirname) && *dirname != '/')
dirname++;
ch = *dirname;
*dirname = 0; /* ensure null termination */
inode = dlook(ffi, inode, fname);
*dirname = ch;
while (*dirname == '/')
dirname++;
}
/* return 1 only if inode exists and is a regular file */
if (! openi(ffi, inode))
return (0);
filepos = 0;
filemax = INODE->ic_sizelo;
return (inode && ((INODE->ic_smode & IFMT) == IFREG));
}
/*
* This is the high-level read function.
*/
static int
ufs_read(fsi_file_t *ffi, char *buf, int len)
{
int off, size, ret = 0, ok;
grub_daddr32_t lblk, dblk;
while (len) {
off = blkoff(SUPERBLOCK, filepos);
lblk = lblkno(SUPERBLOCK, filepos);
size = SUPERBLOCK->fs_bsize;
size -= off;
if (size > len)
size = len;
if ((dblk = sbmap(ffi, lblk)) <= 0) {
/* we are in a file hole, just zero the buf */
grub_memset(buf, 0, size);
} else {
disk_read_func = disk_read_hook;
ok = devread(ffi, fsbtodb(SUPERBLOCK, dblk),
off, size, buf);
disk_read_func = 0;
if (!ok)
return 0;
}
buf += size;
len -= size;
filepos += size;
ret += size;
}
return (ret);
}
int
ufs_embed (int *start_sector, int needed_sectors)
{
if (needed_sectors > 14)
return 0;
*start_sector = 2;
return 1;
}
/* read inode and place content in INODE */
static int
openi(fsi_file_t *ffi, grub_ino_t inode)
{
grub_daddr32_t dblk;
int off;
/* get block and byte offset into the block */
dblk = fsbtodb(SUPERBLOCK, itod(SUPERBLOCK, inode));
off = itoo(SUPERBLOCK, inode) * sizeof (struct icommon);
return (devread(ffi, dblk, off, sizeof (struct icommon), (char *)INODE));
}
/*
* Performs fileblock mapping. Convert file block no. to disk block no.
* Returns 0 when block doesn't exist and <0 when block isn't initialized
* (i.e belongs to a hole in the file).
*/
grub_daddr32_t
sbmap(fsi_file_t *ffi, grub_daddr32_t bn)
{
int level, bound, i, index;
grub_daddr32_t nb, blkno;
grub_daddr32_t *db = INODE->ic_db;
/* blocks 0..UFS_NDADDR are direct blocks */
if (bn < UFS_NDADDR) {
return db[bn];
}
/* determine how many levels of indirection. */
level = 0;
bn -= UFS_NDADDR;
bound = UFS_NINDIR(SUPERBLOCK);
while (bn >= bound) {
level++;
bn -= bound;
bound *= UFS_NINDIR(SUPERBLOCK);
}
if (level >= UFS_NIADDR) /* bn too big */
return ((grub_daddr32_t)0);
/* fetch the first indirect block */
nb = INODE->ic_ib[level];
if (nb == 0) {
return ((grub_daddr32_t)0);
}
if (indirblk0 != nb) {
indirblk0 = 0;
blkno = fsbtodb(SUPERBLOCK, nb);
if (!devread(ffi, blkno, 0, SUPERBLOCK->fs_bsize,
(char *)INDIRBLK0))
return (0);
indirblk0 = nb;
}
bound /= UFS_NINDIR(SUPERBLOCK);
index = (bn / bound) % UFS_NINDIR(SUPERBLOCK);
nb = INDIRBLK0[index];
/* fetch through the indirect blocks */
for (i = 1; i <= level; i++) {
if (indirblk1 != nb) {
blkno = fsbtodb(SUPERBLOCK, nb);
if (!devread(ffi, blkno, 0, SUPERBLOCK->fs_bsize,
(char *)INDIRBLK1))
return (0);
indirblk1 = nb;
}
bound /= UFS_NINDIR(SUPERBLOCK);
index = (bn / bound) % UFS_NINDIR(SUPERBLOCK);
nb = INDIRBLK1[index];
if (nb == 0)
return ((grub_daddr32_t)0);
}
return (nb);
}
/* search directory content for name, return inode number */
static grub_ino_t
dlook(fsi_file_t *ffi, grub_ino_t dir_ino, char *name)
{
int loc, off;
grub_daddr32_t lbn, dbn, dblk;
struct direct *dp;
if ((INODE->ic_smode & IFMT) != IFDIR)
return 0;
loc = 0;
while (loc < INODE->ic_sizelo) {
/* offset into block */
off = blkoff(SUPERBLOCK, loc);
if (off == 0) { /* need to read in a new block */
/* get logical block number */
lbn = lblkno(SUPERBLOCK, loc);
/* resolve indrect blocks */
dbn = sbmap(ffi, lbn);
if (dbn == 0)
return (0);
dblk = fsbtodb(SUPERBLOCK, dbn);
if (!devread(ffi, dblk, 0, SUPERBLOCK->fs_bsize,
(char *)DIRENT)) {
return 0;
}
}
dp = (struct direct *)(DIRENT + off);
if (dp->d_ino && substring(name, dp->d_name) == 0)
return (dp->d_ino);
loc += dp->d_reclen;
}
return (0);
}
fsi_plugin_ops_t *
fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
{
static fsig_plugin_ops_t ops = {
FSIMAGE_PLUGIN_VERSION,
.fpo_mount = ufs_mount,
.fpo_dir = ufs_dir,
.fpo_read = ufs_read
};
*name = "ufs";
return (fsig_init(fp, &ops));
}