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; }
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; }
/* 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; }