type.c revision 194030
199193Sjmallett/* 299193Sjmallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 399193Sjmallett * 499193Sjmallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 599193Sjmallett * FreeBSD project. Redistribution and use in source and binary forms, with 699193Sjmallett * or without modification, are permitted provided that the following 799193Sjmallett * conditions are met: 899193Sjmallett * 999193Sjmallett * 1. Redistribution of source code must retain the above copyright notice, 1099193Sjmallett * this list of conditions and the following disclaimer. 1199193Sjmallett * 2. Redistribution in binary form must reproduce the above copyright 1299193Sjmallett * notice, this list of conditions and the following disclaimer in the 1399193Sjmallett * documentation and/or other materials provided with the distribution. 1499193Sjmallett * 1599193Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1699193Sjmallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1799193Sjmallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1899193Sjmallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1999193Sjmallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2099193Sjmallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2199193Sjmallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2299193Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2399193Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2499193Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2599193Sjmallett * POSSIBILITY OF SUCH DAMAGE. 2699193Sjmallett */ 2799193Sjmallett 2899193Sjmallett#include <sys/cdefs.h> 2999193Sjmallett__FBSDID("$FreeBSD: head/lib/libufs/type.c 194030 2009-06-11 18:04:57Z jmallett $"); 3099193Sjmallett 3199193Sjmallett#include <sys/param.h> 3299193Sjmallett#include <sys/mount.h> 3399193Sjmallett#include <sys/disklabel.h> 3499193Sjmallett#include <sys/stat.h> 3599193Sjmallett 3699193Sjmallett#include <ufs/ufs/ufsmount.h> 3799193Sjmallett#include <ufs/ufs/dinode.h> 3899193Sjmallett#include <ufs/ffs/fs.h> 3999193Sjmallett 4099193Sjmallett#include <errno.h> 4199193Sjmallett#include <fcntl.h> 42109506Sjmallett#include <fstab.h> 43109506Sjmallett#include <paths.h> 4499193Sjmallett#include <stdio.h> 4599193Sjmallett#include <stdlib.h> 4699193Sjmallett#include <string.h> 4799193Sjmallett#include <unistd.h> 4899193Sjmallett 4999193Sjmallett#include <libufs.h> 5099193Sjmallett 51109506Sjmallett/* Internally, track the 'name' value, it's ours. */ 52109506Sjmallett#define MINE_NAME 0x01 53110066Sjmallett/* Track if its fd points to a writable device. */ 54110066Sjmallett#define MINE_WRITE 0x02 55109506Sjmallett 5699193Sjmallettint 5799193Sjmallettufs_disk_close(struct uufsd *disk) 5899193Sjmallett{ 59109462Sjmallett ERROR(disk, NULL); 6099193Sjmallett close(disk->d_fd); 6199193Sjmallett if (disk->d_inoblock != NULL) { 6299193Sjmallett free(disk->d_inoblock); 6399193Sjmallett disk->d_inoblock = NULL; 6499193Sjmallett } 65109506Sjmallett if (disk->d_mine & MINE_NAME) { 66109506Sjmallett free((char *)(uintptr_t)disk->d_name); 67109506Sjmallett disk->d_name = NULL; 68109506Sjmallett } 69116084Sjmallett return (0); 7099193Sjmallett} 7199193Sjmallett 7299193Sjmallettint 7399193Sjmallettufs_disk_fillout(struct uufsd *disk, const char *name) 7499193Sjmallett{ 75109755Sjmallett if (ufs_disk_fillout_blank(disk, name) == -1) { 76116084Sjmallett return (-1); 77109755Sjmallett } 78109755Sjmallett if (sbread(disk) == -1) { 79109755Sjmallett ERROR(disk, "could not read superblock to fill out disk"); 80116084Sjmallett return (-1); 81109755Sjmallett } 82116084Sjmallett return (0); 83109755Sjmallett} 84109755Sjmallett 85109755Sjmallettint 86109755Sjmallettufs_disk_fillout_blank(struct uufsd *disk, const char *name) 87109755Sjmallett{ 88109506Sjmallett struct stat st; 89109506Sjmallett struct fstab *fs; 90167625Spjd struct statfs sfs; 91109506Sjmallett const char *oname; 92109506Sjmallett char dev[MAXPATHLEN]; 93167625Spjd int fd, ret; 9499193Sjmallett 95109462Sjmallett ERROR(disk, NULL); 9699222Sjmallett 97109506Sjmallett oname = name; 98167625Spjdagain: if ((ret = stat(name, &st)) < 0) { 99109506Sjmallett if (*name != '/') { 100109506Sjmallett snprintf(dev, sizeof(dev), "%s%s", _PATH_DEV, name); 101109506Sjmallett name = dev; 102109506Sjmallett goto again; 103109506Sjmallett } 104167625Spjd /* 105167625Spjd * The given object doesn't exist, but don't panic just yet - 106167625Spjd * it may be still mount point listed in /etc/fstab, but without 107167625Spjd * existing corresponding directory. 108167625Spjd */ 109167625Spjd name = oname; 110167625Spjd } 111194030Sjmallett if (ret >= 0 && S_ISREG(st.st_mode)) { 112194030Sjmallett /* Possibly a disk image, give it a try. */ 113194030Sjmallett ; 114194030Sjmallett } else if (ret >= 0 && S_ISCHR(st.st_mode)) { 115167625Spjd /* This is what we need, do nothing. */ 116167625Spjd ; 117167625Spjd } else if ((fs = getfsfile(name)) != NULL) { 118167625Spjd /* 119167625Spjd * The given mount point is listed in /etc/fstab. 120167625Spjd * It is possible that someone unmounted file system by hand 121167625Spjd * and different file system is mounted on this mount point, 122167625Spjd * but we still prefer /etc/fstab entry, because on the other 123167625Spjd * hand, there could be /etc/fstab entry for this mount 124167625Spjd * point, but file system is not mounted yet (eg. noauto) and 125167625Spjd * statfs(2) will point us at different file system. 126167625Spjd */ 127167625Spjd name = fs->fs_spec; 128167625Spjd } else if (ret >= 0 && S_ISDIR(st.st_mode)) { 129167625Spjd /* 130167625Spjd * The mount point is not listed in /etc/fstab, so it may be 131167625Spjd * file system mounted by hand. 132167625Spjd */ 133167625Spjd if (statfs(name, &sfs) < 0) { 134167625Spjd ERROR(disk, "could not find special device"); 135167625Spjd return (-1); 136167625Spjd } 137167625Spjd strlcpy(dev, sfs.f_mntfromname, sizeof(dev)); 138167625Spjd name = dev; 139167625Spjd } else { 140109506Sjmallett ERROR(disk, "could not find special device"); 141116084Sjmallett return (-1); 142109506Sjmallett } 14399193Sjmallett fd = open(name, O_RDONLY); 14499193Sjmallett if (fd == -1) { 145109506Sjmallett ERROR(disk, "could not open special device"); 146116084Sjmallett return (-1); 14799193Sjmallett } 14899193Sjmallett 14999193Sjmallett disk->d_bsize = 1; 150109509Sjmallett disk->d_ccg = 0; 15199193Sjmallett disk->d_fd = fd; 15299193Sjmallett disk->d_inoblock = NULL; 15399823Sjmallett disk->d_inomin = 0; 15499823Sjmallett disk->d_inomax = 0; 155109518Sjmallett disk->d_lcg = 0; 156109506Sjmallett disk->d_mine = 0; 157101687Sjmallett disk->d_ufs = 0; 158105737Sjmallett disk->d_error = NULL; 15999193Sjmallett 160109506Sjmallett if (oname != name) { 161109506Sjmallett name = strdup(name); 162109506Sjmallett if (name == NULL) { 163109506Sjmallett ERROR(disk, "could not allocate memory for disk name"); 164116084Sjmallett return (-1); 165109506Sjmallett } 166109506Sjmallett disk->d_mine |= MINE_NAME; 167109506Sjmallett } 168109506Sjmallett disk->d_name = name; 169109506Sjmallett 170116084Sjmallett return (0); 17199193Sjmallett} 172110066Sjmallett 173110066Sjmallettint 174110066Sjmallettufs_disk_write(struct uufsd *disk) 175110066Sjmallett{ 176110066Sjmallett ERROR(disk, NULL); 177110066Sjmallett 178110066Sjmallett if (disk->d_mine & MINE_WRITE) 179116084Sjmallett return (0); 180110066Sjmallett 181112730Sjmallett close(disk->d_fd); 182110066Sjmallett 183110066Sjmallett disk->d_fd = open(disk->d_name, O_RDWR); 184110066Sjmallett if (disk->d_fd < 0) { 185110066Sjmallett ERROR(disk, "failed to open disk for writing"); 186116084Sjmallett return (-1); 187110066Sjmallett } 188110066Sjmallett 189110066Sjmallett disk->d_mine |= MINE_WRITE; 190110066Sjmallett 191116084Sjmallett return (0); 192110066Sjmallett} 193