Changeset View
Changeset View
Standalone View
Standalone View
lib/libfstyp/fstyp.c
- This file was copied from usr.sbin/fstyp/fstyp.c.
Show All 25 Lines | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
* | * | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/capsicum.h> | |||||
#include <sys/disk.h> | #include <sys/disk.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <capsicum_helpers.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | |||||
#ifdef WITH_ICONV | |||||
#include <iconv.h> | |||||
#endif | |||||
#include <locale.h> | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdint.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | |||||
#include <unistd.h> | |||||
#include <vis.h> | |||||
#ifdef WITH_ICONV | |||||
#include <iconv.h> | |||||
#endif | |||||
#include "fstyp.h" | #include "fstyp.h" | ||||
#include "fstyp_p.h" | |||||
#define LABEL_LEN 256 | bool encodings_enabled = false; | ||||
bool show_label = false; | int fstyp_apfs(FILE *fp, char *label, size_t size); | ||||
int fstyp_cd9660(FILE *fp, char *label, size_t size); | |||||
int fstyp_exfat(FILE *fp, char *label, size_t size); | |||||
int fstyp_ext2fs(FILE *fp, char *label, size_t size); | |||||
int fstyp_geli(FILE *fp, char *label, size_t size); | |||||
int fstyp_hammer(FILE *fp, char *label, size_t size); | |||||
int fstyp_hammer2(FILE *fp, char *label, size_t size); | |||||
int fstyp_hfsp(FILE *fp, char *label, size_t size); | |||||
int fstyp_msdosfs(FILE *fp, char *label, size_t size); | |||||
int fstyp_ntfs(FILE *fp, char *label, size_t size); | |||||
int fstyp_ufs(FILE *fp, char *label, size_t size); | |||||
#ifdef HAVE_ZFS | |||||
int fstyp_zfs(FILE *fp, char *label, size_t size); | |||||
#endif | |||||
typedef int (*fstyp_function)(FILE *, char *, size_t); | static const struct fstype fstypes[] = { | ||||
static struct { | |||||
const char *name; | |||||
fstyp_function function; | |||||
bool unmountable; | |||||
char *precache_encoding; | |||||
} fstypes[] = { | |||||
{ "apfs", &fstyp_apfs, true, NULL }, | { "apfs", &fstyp_apfs, true, NULL }, | ||||
{ "cd9660", &fstyp_cd9660, false, NULL }, | { "cd9660", &fstyp_cd9660, false, NULL }, | ||||
{ "exfat", &fstyp_exfat, false, EXFAT_ENC }, | { "exfat", &fstyp_exfat, false, EXFAT_ENC }, | ||||
{ "ext2fs", &fstyp_ext2fs, false, NULL }, | { "ext2fs", &fstyp_ext2fs, false, NULL }, | ||||
{ "geli", &fstyp_geli, true, NULL }, | { "geli", &fstyp_geli, true, NULL }, | ||||
{ "hammer", &fstyp_hammer, true, NULL }, | { "hammer", &fstyp_hammer, true, NULL }, | ||||
{ "hammer2", &fstyp_hammer2, true, NULL }, | { "hammer2", &fstyp_hammer2, true, NULL }, | ||||
{ "hfs+", &fstyp_hfsp, false, NULL }, | { "hfs+", &fstyp_hfsp, false, NULL }, | ||||
{ "msdosfs", &fstyp_msdosfs, false, NULL }, | { "msdosfs", &fstyp_msdosfs, false, NULL }, | ||||
{ "ntfs", &fstyp_ntfs, false, NTFS_ENC }, | { "ntfs", &fstyp_ntfs, false, NTFS_ENC }, | ||||
{ "ufs", &fstyp_ufs, false, NULL }, | { "ufs", &fstyp_ufs, false, NULL }, | ||||
#ifdef HAVE_ZFS | #ifdef HAVE_ZFS | ||||
{ "zfs", &fstyp_zfs, true, NULL }, | { "zfs", &fstyp_zfs, true, NULL }, | ||||
#endif | #endif | ||||
{ NULL, NULL, NULL, NULL } | { NULL, NULL, NULL, NULL } | ||||
}; | }; | ||||
void * | void * | ||||
read_buf(FILE *fp, off_t off, size_t len) | read_buf(FILE *fp, off_t off, size_t len) | ||||
{ | { | ||||
int error; | int error; | ||||
size_t nread; | size_t nread; | ||||
void *buf; | void *buf; | ||||
error = fseek(fp, off, SEEK_SET); | error = fseek(fp, off, SEEK_SET); | ||||
Show All 14 Lines | if (nread != 1) { | ||||
if (feof(fp) == 0) | if (feof(fp) == 0) | ||||
warn("fread"); | warn("fread"); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
return (buf); | return (buf); | ||||
} | } | ||||
char * | |||||
checked_strdup(const char *s) | |||||
{ | |||||
char *c; | |||||
c = strdup(s); | |||||
if (c == NULL) | |||||
err(1, "strdup"); | |||||
return (c); | |||||
} | |||||
void | |||||
rtrim(char *label, size_t size) | |||||
{ | |||||
ptrdiff_t i; | |||||
for (i = size - 1; i >= 0; i--) { | |||||
if (label[i] == '\0') | |||||
continue; | |||||
else if (label[i] == ' ') | |||||
label[i] = '\0'; | |||||
else | |||||
break; | |||||
} | |||||
} | |||||
static void | static void | ||||
usage(void) | |||||
{ | |||||
fprintf(stderr, "usage: fstyp [-l] [-s] [-u] special\n"); | |||||
exit(1); | |||||
} | |||||
static void | |||||
type_check(const char *path, FILE *fp) | type_check(const char *path, FILE *fp) | ||||
{ | { | ||||
int error, fd; | int error, fd; | ||||
off_t mediasize; | off_t mediasize; | ||||
struct stat sb; | struct stat sb; | ||||
fd = fileno(fp); | fd = fileno(fp); | ||||
error = fstat(fd, &sb); | error = fstat(fd, &sb); | ||||
if (error != 0) | if (error != 0) | ||||
err(1, "%s: fstat", path); | err(1, "%s: fstat", path); | ||||
if (S_ISREG(sb.st_mode)) | if (S_ISREG(sb.st_mode)) | ||||
return; | return; | ||||
error = ioctl(fd, DIOCGMEDIASIZE, &mediasize); | error = ioctl(fd, DIOCGMEDIASIZE, &mediasize); | ||||
if (error != 0) | if (error != 0) | ||||
errx(1, "%s: not a disk", path); | errx(1, "%s: not a disk", path); | ||||
} | } | ||||
int | void | ||||
main(int argc, char **argv) | rtrim(char *label, size_t size) | ||||
{ | { | ||||
int ch, error, i, nbytes; | ptrdiff_t i; | ||||
bool ignore_type = false, show_unmountable = false; | |||||
char label[LABEL_LEN + 1], strvised[LABEL_LEN * 4 + 1]; | |||||
char *path; | |||||
FILE *fp; | |||||
fstyp_function fstyp_f; | |||||
while ((ch = getopt(argc, argv, "lsu")) != -1) { | for (i = size - 1; i >= 0; i--) { | ||||
switch (ch) { | if (label[i] == '\0') | ||||
case 'l': | continue; | ||||
show_label = true; | else if (label[i] == ' ') | ||||
label[i] = '\0'; | |||||
else | |||||
break; | break; | ||||
case 's': | |||||
ignore_type = true; | |||||
break; | |||||
case 'u': | |||||
show_unmountable = true; | |||||
break; | |||||
default: | |||||
usage(); | |||||
} | } | ||||
} | } | ||||
argc -= optind; | void | ||||
argv += optind; | enable_encodings() | ||||
if (argc != 1) | { | ||||
usage(); | encodings_enabled = true; | ||||
path = argv[0]; | |||||
if (setlocale(LC_CTYPE, "") == NULL) | |||||
err(1, "setlocale"); | |||||
caph_cache_catpages(); | |||||
#ifdef WITH_ICONV | #ifdef WITH_ICONV | ||||
int i; | |||||
/* Cache iconv conversion data before entering capability mode. */ | /* Cache iconv conversion data before entering capability mode. */ | ||||
if (show_label) { | |||||
for (i = 0; i < nitems(fstypes); i++) { | for (i = 0; i < nitems(fstypes); i++) { | ||||
iconv_t cd; | iconv_t cd; | ||||
if (fstypes[i].precache_encoding == NULL) | if (fstypes[i].precache_encoding == NULL) | ||||
continue; | continue; | ||||
cd = iconv_open("", fstypes[i].precache_encoding); | cd = iconv_open("", fstypes[i].precache_encoding); | ||||
if (cd == (iconv_t)-1) | if (cd == (iconv_t)-1) | ||||
err(1, "%s: iconv_open %s", fstypes[i].name, | err(1, "%s: iconv_open %s", fstypes[i].name, | ||||
fstypes[i].precache_encoding); | fstypes[i].precache_encoding); | ||||
/* Iconv keeps a small cache of unused encodings. */ | /* Iconv keeps a small cache of unused encodings. */ | ||||
iconv_close(cd); | iconv_close(cd); | ||||
} | } | ||||
} | |||||
#endif | #endif | ||||
} | |||||
fp = fopen(path, "r"); | int | ||||
if (fp == NULL) | fstypef(FILE *fp, char *label, size_t label_len, bool show_unmountable, const struct fstype **result) | ||||
err(1, "%s", path); | { | ||||
int error, i; | |||||
fstyp_function fstyp_f; | |||||
if (caph_enter() < 0) | *result = NULL; | ||||
err(1, "cap_enter"); | error = -1; | ||||
if (ignore_type == false) | |||||
type_check(path, fp); | |||||
memset(label, '\0', sizeof(label)); | |||||
for (i = 0;; i++) { | for (i = 0;; i++) { | ||||
if (show_unmountable == false && fstypes[i].unmountable == true) | if (show_unmountable == false && fstypes[i].unmountable == true) | ||||
continue; | continue; | ||||
*result = &fstypes[i]; | |||||
fstyp_f = fstypes[i].function; | fstyp_f = fstypes[i].function; | ||||
if (fstyp_f == NULL) | if (fstyp_f == NULL) | ||||
break; | return -1; | ||||
error = fstyp_f(fp, label, sizeof(label)); | error = fstyp_f(fp, label, label_len); | ||||
if (error == 0) | if (error == 0) | ||||
break; | break; | ||||
} | } | ||||
if (fstypes[i].name == NULL) { | return error; | ||||
warnx("%s: filesystem not recognized", path); | } | ||||
return (1); | No newline at end of file | ||||
} | |||||
if (show_label && label[0] != '\0') { | |||||
/* | |||||
* XXX: I'd prefer VIS_HTTPSTYLE, but it unconditionally | |||||
* encodes spaces. | |||||
*/ | |||||
nbytes = strsnvis(strvised, sizeof(strvised), label, | |||||
VIS_GLOB | VIS_NL, "\"'$"); | |||||
if (nbytes == -1) | |||||
err(1, "strsnvis"); | |||||
printf("%s %s\n", fstypes[i].name, strvised); | |||||
} else { | |||||
printf("%s\n", fstypes[i].name); | |||||
} | |||||
return (0); | |||||
} |