|
60 | 60 | #include <fnmatch.h> |
61 | 61 | #include <limits.h> |
62 | 62 | #include <fcntl.h> |
| 63 | +#include <sys/statvfs.h> /* statvfs(3) */ |
63 | 64 |
|
64 | 65 | #if defined(__linux__) |
| 66 | +#include <sys/statfs.h> /* statfs() for f_type */ |
65 | 67 | #define HAS_IOCTL |
66 | 68 | #endif |
67 | 69 |
|
@@ -1779,6 +1781,89 @@ uc_fs_lstat(uc_vm_t *vm, size_t nargs) |
1779 | 1781 | return uc_fs_stat_common(vm, nargs, true); |
1780 | 1782 | } |
1781 | 1783 |
|
| 1784 | +/** |
| 1785 | + * @typedef {Object} module:fs.StatVFSResult |
| 1786 | + * @property {number} bsize file system block size |
| 1787 | + * @property {number} frsize fragment size |
| 1788 | + * @property {number} blocks total blocks |
| 1789 | + * @property {number} bfree free blocks |
| 1790 | + * @property {number} bavail free blocks available to unprivileged users |
| 1791 | + * @property {number} files total file nodes (inodes) |
| 1792 | + * @property {number} ffree free file nodes |
| 1793 | + * @property {number} favail free nodes available to unprivileged users |
| 1794 | + * @property {number} fsid file system id |
| 1795 | + * @property {number} flag mount flags |
| 1796 | + * @property {number} namemax maximum filename length |
| 1797 | + * @property {number} freesize free space in bytes (calculated as `frsize * bfree`) |
| 1798 | + * @property {number} totalsize total size of the filesystem (calculated as `frsize * blocks`) |
| 1799 | + * @property {number} type (Linux only) magic number of the filesystem, obtained from `statfs` |
| 1800 | + */ |
| 1801 | + |
| 1802 | +/** |
| 1803 | + * Query filesystem statistics for a given pathname. |
| 1804 | + * |
| 1805 | + * The returned object mirrors the members of `struct statvfs`. |
| 1806 | + * Convenience properties `freesize` and `totalsize` are added, |
| 1807 | + * which are calculated as: |
| 1808 | + * - `frsize * bfree` to provide the free space in bytes and |
| 1809 | + * - `frsize * blocks` to provide the total size of the filesystem. |
| 1810 | + * |
| 1811 | + * On Linux an additional `type` field (magic number from `statfs`) is |
| 1812 | + * provided if the call succeeds. |
| 1813 | + * |
| 1814 | + * Returns `null` on failure (and sets `fs.last_error`). |
| 1815 | + * |
| 1816 | + * @function module:fs#statvfs |
| 1817 | + * |
| 1818 | + * @param {string} path |
| 1819 | + * The path to the directory or file with which to query the filesystem. |
| 1820 | + * |
| 1821 | + * @returns {?module:fs.StatVFSResult} |
| 1822 | + * |
| 1823 | + * @example |
| 1824 | + * // Get filesystem statistics for a path |
| 1825 | + * const stats = statvfs('path/to/directory'); |
| 1826 | + * print(stats.bsize); // file system block size |
| 1827 | + */ |
| 1828 | +static uc_value_t * |
| 1829 | +uc_fs_statvfs(uc_vm_t *vm, size_t nargs) |
| 1830 | +{ |
| 1831 | + uc_value_t *path = uc_fn_arg(0); |
| 1832 | + struct statvfs sv; |
| 1833 | + |
| 1834 | + if (ucv_type(path) != UC_STRING) |
| 1835 | + err_return(EINVAL); |
| 1836 | + |
| 1837 | + if (statvfs(ucv_string_get(path), &sv) == -1) |
| 1838 | + err_return(errno); |
| 1839 | + |
| 1840 | + uc_value_t *o = ucv_object_new(vm); |
| 1841 | + |
| 1842 | + ucv_object_add(o, "bsize", ucv_int64_new(sv.f_bsize)); |
| 1843 | + ucv_object_add(o, "frsize", ucv_int64_new(sv.f_frsize)); |
| 1844 | + ucv_object_add(o, "blocks", ucv_int64_new(sv.f_blocks)); |
| 1845 | + ucv_object_add(o, "bfree", ucv_int64_new(sv.f_bfree)); |
| 1846 | + ucv_object_add(o, "bavail", ucv_int64_new(sv.f_bavail)); |
| 1847 | + ucv_object_add(o, "files", ucv_int64_new(sv.f_files)); |
| 1848 | + ucv_object_add(o, "ffree", ucv_int64_new(sv.f_ffree)); |
| 1849 | + ucv_object_add(o, "favail", ucv_int64_new(sv.f_favail)); |
| 1850 | + ucv_object_add(o, "fsid", ucv_int64_new(sv.f_fsid)); |
| 1851 | + ucv_object_add(o, "flag", ucv_int64_new(sv.f_flag)); |
| 1852 | + ucv_object_add(o, "namemax", ucv_int64_new(sv.f_namemax)); |
| 1853 | + ucv_object_add(o, "freesize", ucv_int64_new(sv.f_frsize * sv.f_bfree)); |
| 1854 | + ucv_object_add(o, "totalsize",ucv_int64_new(sv.f_frsize * sv.f_blocks)); |
| 1855 | + |
| 1856 | +#ifdef __linux__ |
| 1857 | + /* Call statfs to expose the magic number (`f_type`) */ |
| 1858 | + struct statfs sf; |
| 1859 | + if (statfs(ucv_string_get(path), &sf) == 0) { |
| 1860 | + ucv_object_add(o, "type", ucv_int64_new(sf.f_type)); |
| 1861 | + } |
| 1862 | +#endif |
| 1863 | + |
| 1864 | + return o; |
| 1865 | +} |
| 1866 | + |
1782 | 1867 | /** |
1783 | 1868 | * Creates a new directory. |
1784 | 1869 | * |
@@ -3024,6 +3109,7 @@ static const uc_function_list_t global_fns[] = { |
3024 | 3109 | { "popen", uc_fs_popen }, |
3025 | 3110 | { "readlink", uc_fs_readlink }, |
3026 | 3111 | { "stat", uc_fs_stat }, |
| 3112 | + { "statvfs", uc_fs_statvfs }, |
3027 | 3113 | { "lstat", uc_fs_lstat }, |
3028 | 3114 | { "mkdir", uc_fs_mkdir }, |
3029 | 3115 | { "rmdir", uc_fs_rmdir }, |
|
0 commit comments