1 /* 2 * Copyright (c) 2017 Cyril Hrubis <chrubis (at) suse.cz> 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <stdio.h> 19 #include <errno.h> 20 #include <stdlib.h> 21 #include <sys/mount.h> 22 #include <sys/wait.h> 23 24 #define TST_NO_DEFAULT_MAIN 25 #include "tst_test.h" 26 #include "tst_fs.h" 27 28 static const char *const fs_type_whitelist[] = { 29 "ext2", 30 "ext3", 31 "ext4", 32 "xfs", 33 "btrfs", 34 "vfat", 35 "exfat", 36 "ntfs", 37 NULL 38 }; 39 40 static const char *fs_types[ARRAY_SIZE(fs_type_whitelist)]; 41 42 static int has_mkfs(const char *fs_type) 43 { 44 char buf[128]; 45 int ret; 46 47 sprintf(buf, "mkfs.%s >/dev/null 2>&1", fs_type); 48 49 ret = tst_system(buf); 50 51 if (WEXITSTATUS(ret) == 127) { 52 tst_res(TINFO, "mkfs.%s does not exist", fs_type); 53 return 0; 54 } 55 56 tst_res(TINFO, "mkfs.%s does exist", fs_type); 57 return 1; 58 } 59 60 static int has_kernel_support(const char *fs_type) 61 { 62 static int fuse_supported = -1; 63 const char *tmpdir = getenv("TMPDIR"); 64 char buf[128]; 65 int ret; 66 67 if (!tmpdir) 68 tmpdir = "/tmp"; 69 70 mount("/dev/zero", tmpdir, fs_type, 0, NULL); 71 if (errno != ENODEV) { 72 tst_res(TINFO, "Kernel supports %s", fs_type); 73 return 1; 74 } 75 76 /* Is FUSE supported by kernel? */ 77 if (fuse_supported == -1) { 78 ret = open("/dev/fuse", O_RDWR); 79 if (ret < 0) { 80 fuse_supported = 0; 81 } else { 82 fuse_supported = 1; 83 SAFE_CLOSE(ret); 84 } 85 } 86 87 if (!fuse_supported) 88 return 0; 89 90 /* Is FUSE implementation installed? */ 91 sprintf(buf, "mount.%s >/dev/null 2>&1", fs_type); 92 93 ret = tst_system(buf); 94 if (WEXITSTATUS(ret) == 127) { 95 tst_res(TINFO, "Filesystem %s is not supported", fs_type); 96 return 0; 97 } 98 99 tst_res(TINFO, "FUSE does support %s", fs_type); 100 return 1; 101 } 102 103 static int is_supported(const char *fs_type) 104 { 105 return has_kernel_support(fs_type) && has_mkfs(fs_type); 106 } 107 108 const char **tst_get_supported_fs_types(void) 109 { 110 unsigned int i, j = 0; 111 112 for (i = 0; fs_type_whitelist[i]; i++) { 113 if (is_supported(fs_type_whitelist[i])) 114 fs_types[j++] = fs_type_whitelist[i]; 115 } 116 117 return fs_types; 118 } 119