Esempio n. 1
0
struct fs_superblock *
fs_iterate_superblocks(fs_t * fs, struct fs_superblock * sb)
{
    mtx_t * lock = &fs->fs_giant;

    mtx_lock(lock);

    if (SLIST_EMPTY(&fs->sblist_head)) {
        mtx_unlock(lock);
        return NULL;
    }

    /* Get the next sb and skip filesytems that are inherited for fs */
    do {
        if (!sb)
            sb = SLIST_FIRST(&fs->sblist_head);
        else
            sb = SLIST_NEXT(sb, _sblist);
    } while (sb && DEV_MAJOR(sb->vdev_id) != fs->fs_majornum);

    mtx_unlock(lock);

    return sb;
}
Esempio n. 2
0
File: mbr.c Progetto: htchiang/zeke
int mbr_register(int fd, int * part_count)
{
    file_t * file;
    vnode_t * parent_vnode;
    struct dev_info * parent;
    uint8_t * block_0 = NULL;
    int parts = 0;
    int retval = 0;

#ifdef configMBR_DEBUG
    KERROR(KERROR_DEBUG, "%s(fd: %d, part_count: %p)\n", __func__,
           fd, part_count);
#endif

    file = fs_fildes_ref(curproc->files, fd, 1);

    parent_vnode = file->vnode;
    parent = (struct dev_info *)parent_vnode->vn_specinfo;
    if (!(S_ISBLK(parent_vnode->vn_mode) || S_ISCHR(parent_vnode->vn_mode))) {
        KERROR(KERROR_ERR, "MBR: not a device\n");

        retval = -ENODEV;
        goto fail;
    }

    /* Check the validity of the parent device. */
    if (!parent) {
        KERROR(KERROR_ERR, "MBR: invalid parent device\n");

        retval = -ENODEV;
        goto fail;
    }

    block_0 = kmalloc(MBR_SIZE);
    if (!block_0) {
        retval = -ENOMEM;
        goto fail;
    }

#ifdef configMBR_DEBUG
    KERROR(KERROR_DEBUG,
           "MBR: reading block 0 from device %s\n",
           parent->dev_name);
#endif

    retval = read_block_0(block_0, file);
    if (retval)
        goto fail;
    retval = check_signature(block_0);
    if (retval)
        goto fail;

#ifdef configMBR_DEBUG
    KERROR(KERROR_DEBUG,
             "MBR: found valid MBR on device %s\n", parent->dev_name);
#endif

    /*
     * If parent block size is not MBR_SIZE, we have to coerce start_block
     * and blocks to fit.
     */
    if (parent->block_size < MBR_SIZE) {
        /* We do not support parent device block sizes < 512 */
        KERROR(KERROR_ERR,
                 "MBR: block size of %s is too small (%i)\n",
                 parent->dev_name, parent->block_size);

        retval = -ENOTSUP;
        goto fail;
    }

    uint32_t block_size_adjust = parent->block_size / MBR_SIZE;
    if (parent->block_size % MBR_SIZE) {
        /*
         * We do not support parent device block sizes that are not
         * multiples of 512.
         */
        KERROR(KERROR_ERR,
               "MBR: block size of %s is not a multiple of 512 (%i)\n",
               parent->dev_name, parent->block_size);

        retval = -ENOTSUP;
        goto fail;
    }

#ifdef configMBR_DEBUG
    if (block_size_adjust > 1) {
        KERROR(KERROR_DEBUG, "MBR: block_size_adjust: %i\n",
                 block_size_adjust);
    }
#endif

    int major_num = DEV_MAJOR(parent->dev_id) + 1;
    for (size_t i = 0; i < 4; i++) {
        size_t p_offset = 0x1be + (i * 0x10);
        struct mbr_dev * d;

        if (block_0[p_offset + 4] == 0x00) {
            /* Invalid partition */
            continue;
        }

        d = kzalloc(sizeof(struct mbr_dev));
        if (!d) {
            KERROR(KERROR_ERR, "MBR: Out of memory");

            retval = -ENOMEM;
            break;
        }

        d->dev.dev_id = DEV_MMTODEV(major_num, mbr_dev_count);
        d->dev.drv_name = driver_name;
        ksprintf(d->dev.dev_name, sizeof(d->dev.dev_name), "%sp%u",
                 parent->dev_name, i);
        d->dev.read = mbr_read;
        d->dev.write = (parent->write) ? mbr_write : NULL;
        d->dev.block_size = parent->block_size;
        d->dev.flags = parent->flags;
        d->part_no = i;
        d->part_id = block_0[p_offset + 4];
        d->start_block = read_word(block_0, p_offset + 8);
        d->blocks = read_word(block_0, p_offset + 12);
        d->parent = parent;

        /* Adjust start_block and blocks to the parent block size */
        if (d->start_block % block_size_adjust) {
            KERROR(KERROR_ERR,
                   "MBR: partition number %i on %s does not start on a block "
                   "boundary (%i).\n",
                   d->part_no, parent->dev_name, d->start_block);

            retval = -EFAULT;
            goto fail;
        }
        d->start_block /= block_size_adjust;

        if (d->blocks % block_size_adjust) {
            KERROR(KERROR_ERR,
                   "MBR: partition number %i on %s does not have a length "
                   "that is an exact multiple of the block length (%i).\n",
                   d->part_no, parent->dev_name, d->start_block);

            retval = -EFAULT;
            goto fail;
        }
        d->blocks /= block_size_adjust;
        d->dev.num_blocks = d->blocks;

#ifdef configMBR_DEBUG
        KERROR(KERROR_DEBUG,
               "MBR: partition number %i (%s) of type %x, "
               "start sector %u, sector count %u, p_offset %03x\n",
               d->part_no, d->dev.dev_name, d->part_id,
               d->start_block, d->blocks, p_offset);
#endif

        make_dev(&d->dev, 0, 0, 0666, NULL);
        mbr_dev_count++;
        parts++;

        /* Register the fs */
        //register_fs__((struct dev_info *)d, d->part_id);
        /* TODO Register the fs dev with devfs */
    }

    KERROR(KERROR_INFO, "MBR: found total of %i partition(s)\n",
           parts);

fail:
    kfree(block_0);
    fs_fildes_ref(curproc->files, fd, -1);

    if (retval != 0) {
        KERROR(KERROR_ERR, "MBR registration failed on device: \"%s\"\n",
               parent->dev_name);
    }

    return retval;
}
Esempio n. 3
0
/* If we have a --backup-dir, then we get here from make_backup().
 * We will move the file to be deleted into a parallel directory tree. */
static int keep_backup(const char *fname)
{
	STRUCT_STAT st;
	struct file_struct *file;
	char *buf;
	int kept = 0;
	int ret_code;

	/* return if no file to keep */
	if (do_lstat(fname, &st) < 0)
		return 1;

	if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
		return 1; /* the file could have disappeared */

	if (!(buf = get_backup_name(fname))) {
		unmake_file(file);
		return 0;
	}

	/* Check to see if this is a device file, or link */
	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
	 || (preserve_specials && IS_SPECIAL(file->mode))) {
		uint32 *devp = F_RDEV_P(file);
		dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
		do_unlink(buf);
		if (do_mknod(buf, file->mode, rdev) < 0
		    && (errno != ENOENT || make_bak_dir(buf) < 0
		     || do_mknod(buf, file->mode, rdev) < 0)) {
			rsyserr(FERROR, errno, "mknod %s failed",
				full_fname(buf));
		} else if (verbose > 2) {
			rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
				fname);
		}
		kept = 1;
		do_unlink(fname);
	}

	if (!kept && S_ISDIR(file->mode)) {
		/* make an empty directory */
		if (do_mkdir(buf, file->mode) < 0
		    && (errno != ENOENT || make_bak_dir(buf) < 0
		     || do_mkdir(buf, file->mode) < 0)) {
			rsyserr(FINFO, errno, "mkdir %s failed",
				full_fname(buf));
		}

		ret_code = do_rmdir(fname);
		if (verbose > 2) {
			rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
				full_fname(fname), ret_code);
		}
		kept = 1;
	}

#ifdef SUPPORT_LINKS
	if (!kept && preserve_links && S_ISLNK(file->mode)) {
		const char *sl = F_SYMLINK(file);
		if (safe_symlinks && unsafe_symlink(sl, buf)) {
			if (verbose) {
				rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
					full_fname(buf), sl);
			}
			kept = 1;
		} else {
			do_unlink(buf);
			if (do_symlink(sl, buf) < 0
			    && (errno != ENOENT || make_bak_dir(buf) < 0
			     || do_symlink(sl, buf) < 0)) {
				rsyserr(FERROR, errno, "link %s -> \"%s\"",
					full_fname(buf), sl);
			}
			do_unlink(fname);
			kept = 1;
		}
	}
#endif

	if (!kept && !S_ISREG(file->mode)) {
		rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
			fname);
		unmake_file(file);
		return 1;
	}

	/* move to keep tree if a file */
	if (!kept) {
		if (robust_move(fname, buf) != 0) {
			rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
				full_fname(fname), buf);
		} else if (st.st_nlink > 1) {
			/* If someone has hard-linked the file into the backup
			 * dir, rename() might return success but do nothing! */
			robust_unlink(fname); /* Just in case... */
		}
	}
	set_file_attrs(buf, file, NULL, 0);
	unmake_file(file);

	if (verbose > 1) {
		rprintf(FINFO, "backed up %s to %s\n",
			fname, buf);
	}
	return 1;
}