Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the MicroPython project, http://micropython.org/ |
| 3 | * |
| 4 | * The MIT License (MIT) |
| 5 | * |
| 6 | * Copyright (c) 2014 Damien P. George |
| 7 | * Copyright (c) 2016 Paul Sokolovsky |
| 8 | * |
| 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 10 | * of this software and associated documentation files (the "Software"), to deal |
| 11 | * in the Software without restriction, including without limitation the rights |
| 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 13 | * copies of the Software, and to permit persons to whom the Software is |
| 14 | * furnished to do so, subject to the following conditions: |
| 15 | * |
| 16 | * The above copyright notice and this permission notice shall be included in |
| 17 | * all copies or substantial portions of the Software. |
| 18 | * |
| 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 25 | * THE SOFTWARE. |
| 26 | */ |
| 27 | |
| 28 | #include "py/mpconfig.h" |
| 29 | #if MICROPY_VFS_FAT |
| 30 | |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 31 | #if !MICROPY_FATFS_OO |
| 32 | #error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_FATFS_OO" |
| 33 | #endif |
| 34 | |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 35 | #include <string.h> |
Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 36 | #include "py/nlr.h" |
| 37 | #include "py/runtime.h" |
Alex March | d02f3a5 | 2016-09-28 14:51:35 +0100 | [diff] [blame] | 38 | #include "py/mperrno.h" |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 39 | #include "lib/oofatfs/ff.h" |
Paul Sokolovsky | 6b0c882 | 2016-02-15 00:16:46 +0200 | [diff] [blame] | 40 | #include "extmod/vfs_fat_file.h" |
Damien George | f9dc644 | 2016-05-20 12:43:32 +0100 | [diff] [blame] | 41 | #include "extmod/fsusermount.h" |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 42 | #include "timeutils.h" |
Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 43 | |
| 44 | #define mp_obj_fat_vfs_t fs_user_mount_t |
| 45 | |
| 46 | STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { |
| 47 | mp_arg_check_num(n_args, n_kw, 2, 2, false); |
| 48 | mp_obj_fat_vfs_t *vfs = fatfs_mount_mkfs(n_args, args, (mp_map_t*)&mp_const_empty_map, false); |
| 49 | vfs->base.type = type; |
Paul Sokolovsky | 1bb15ca | 2016-02-14 16:21:27 +0200 | [diff] [blame] | 50 | return MP_OBJ_FROM_PTR(vfs); |
Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { |
| 54 | mp_obj_t args[] = {bdev_in, MP_OBJ_NEW_QSTR(MP_QSTR_mkfs)}; |
| 55 | fatfs_mount_mkfs(2, args, (mp_map_t*)&mp_const_empty_map, true); |
| 56 | return mp_const_none; |
| 57 | } |
| 58 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); |
| 59 | STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj)); |
| 60 | |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 61 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(fat_vfs_open_obj, 2, fatfs_builtin_open_self); |
Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 62 | |
Paul Sokolovsky | cd6d189 | 2016-02-28 17:17:24 +0200 | [diff] [blame] | 63 | STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 64 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]); |
Paul Sokolovsky | cd6d189 | 2016-02-28 17:17:24 +0200 | [diff] [blame] | 65 | bool is_str_type = true; |
| 66 | const char *path; |
| 67 | if (n_args == 2) { |
| 68 | if (mp_obj_get_type(args[1]) == &mp_type_bytes) { |
| 69 | is_str_type = false; |
| 70 | } |
| 71 | path = mp_obj_str_get_str(args[1]); |
| 72 | } else { |
| 73 | path = ""; |
| 74 | } |
| 75 | |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 76 | return fat_vfs_listdir2(self, path, is_str_type); |
Paul Sokolovsky | cd6d189 | 2016-02-28 17:17:24 +0200 | [diff] [blame] | 77 | } |
| 78 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_listdir_obj, 1, 2, fat_vfs_listdir_func); |
| 79 | |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 80 | STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) { |
| 81 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
Paul Sokolovsky | 19749db | 2016-02-28 20:30:07 +0200 | [diff] [blame] | 82 | const char *path = mp_obj_str_get_str(path_in); |
Alex March | d02f3a5 | 2016-09-28 14:51:35 +0100 | [diff] [blame] | 83 | |
| 84 | FILINFO fno; |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 85 | FRESULT res = f_stat(&self->fatfs, path, &fno); |
Alex March | d02f3a5 | 2016-09-28 14:51:35 +0100 | [diff] [blame] | 86 | |
| 87 | if (res != FR_OK) { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 88 | mp_raise_OSError(fresult_to_errno_table[res]); |
Paul Sokolovsky | 19749db | 2016-02-28 20:30:07 +0200 | [diff] [blame] | 89 | } |
Alex March | d02f3a5 | 2016-09-28 14:51:35 +0100 | [diff] [blame] | 90 | |
| 91 | // check if path is a file or directory |
| 92 | if ((fno.fattrib & AM_DIR) == attr) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 93 | res = f_unlink(&self->fatfs, path); |
Alex March | d02f3a5 | 2016-09-28 14:51:35 +0100 | [diff] [blame] | 94 | |
| 95 | if (res != FR_OK) { |
| 96 | mp_raise_OSError(fresult_to_errno_table[res]); |
| 97 | } |
| 98 | return mp_const_none; |
| 99 | } else { |
| 100 | mp_raise_OSError(attr ? MP_ENOTDIR : MP_EISDIR); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 105 | return fat_vfs_remove_internal(vfs_in, path_in, 0); // 0 == file attribute |
Paul Sokolovsky | 19749db | 2016-02-28 20:30:07 +0200 | [diff] [blame] | 106 | } |
| 107 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove); |
| 108 | |
Paul Sokolovsky | 0a6f599 | 2016-07-16 03:46:42 +0300 | [diff] [blame] | 109 | STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 110 | return fat_vfs_remove_internal(vfs_in, path_in, AM_DIR); |
Paul Sokolovsky | 0a6f599 | 2016-07-16 03:46:42 +0300 | [diff] [blame] | 111 | } |
| 112 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir); |
| 113 | |
Paul Sokolovsky | e082183 | 2016-02-29 01:22:38 +0200 | [diff] [blame] | 114 | STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 115 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
Paul Sokolovsky | e082183 | 2016-02-29 01:22:38 +0200 | [diff] [blame] | 116 | const char *old_path = mp_obj_str_get_str(path_in); |
| 117 | const char *new_path = mp_obj_str_get_str(path_out); |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 118 | FRESULT res = f_rename(&self->fatfs, old_path, new_path); |
Damien George | b7df3e5 | 2016-12-02 15:06:09 +1100 | [diff] [blame] | 119 | if (res == FR_EXIST) { |
| 120 | // if new_path exists then try removing it (but only if it's a file) |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 121 | fat_vfs_remove_internal(vfs_in, path_out, 0); // 0 == file attribute |
Damien George | b7df3e5 | 2016-12-02 15:06:09 +1100 | [diff] [blame] | 122 | // try to rename again |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 123 | res = f_rename(&self->fatfs, old_path, new_path); |
Damien George | b7df3e5 | 2016-12-02 15:06:09 +1100 | [diff] [blame] | 124 | } |
Robert HH | 7c004e7 | 2016-05-27 22:28:00 +0200 | [diff] [blame] | 125 | if (res == FR_OK) { |
| 126 | return mp_const_none; |
| 127 | } else { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 128 | mp_raise_OSError(fresult_to_errno_table[res]); |
Paul Sokolovsky | e082183 | 2016-02-29 01:22:38 +0200 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | } |
| 132 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename); |
| 133 | |
Paul Sokolovsky | bbe832a | 2016-02-29 00:02:50 +0200 | [diff] [blame] | 134 | STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 135 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
Paul Sokolovsky | bbe832a | 2016-02-29 00:02:50 +0200 | [diff] [blame] | 136 | const char *path = mp_obj_str_get_str(path_o); |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 137 | FRESULT res = f_mkdir(&self->fatfs, path); |
Robert HH | 7c004e7 | 2016-05-27 22:28:00 +0200 | [diff] [blame] | 138 | if (res == FR_OK) { |
| 139 | return mp_const_none; |
| 140 | } else { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 141 | mp_raise_OSError(fresult_to_errno_table[res]); |
Paul Sokolovsky | bbe832a | 2016-02-29 00:02:50 +0200 | [diff] [blame] | 142 | } |
| 143 | } |
| 144 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir); |
| 145 | |
Paul Sokolovsky | f12146c | 2016-05-29 18:17:00 +0300 | [diff] [blame] | 146 | /// Change current directory. |
Paul Sokolovsky | ee5e3f6 | 2016-05-29 18:52:41 +0300 | [diff] [blame] | 147 | STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 148 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
Paul Sokolovsky | f12146c | 2016-05-29 18:17:00 +0300 | [diff] [blame] | 149 | const char *path; |
| 150 | path = mp_obj_str_get_str(path_in); |
| 151 | |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 152 | FRESULT res = f_chdir(&self->fatfs, path); |
Paul Sokolovsky | f12146c | 2016-05-29 18:17:00 +0300 | [diff] [blame] | 153 | |
| 154 | if (res != FR_OK) { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 155 | mp_raise_OSError(fresult_to_errno_table[res]); |
Paul Sokolovsky | f12146c | 2016-05-29 18:17:00 +0300 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | return mp_const_none; |
| 159 | } |
Paul Sokolovsky | ee5e3f6 | 2016-05-29 18:52:41 +0300 | [diff] [blame] | 160 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir); |
Paul Sokolovsky | f12146c | 2016-05-29 18:17:00 +0300 | [diff] [blame] | 161 | |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 162 | /// Get the current directory. |
Paul Sokolovsky | ee5e3f6 | 2016-05-29 18:52:41 +0300 | [diff] [blame] | 163 | STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 164 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 165 | char buf[MICROPY_ALLOC_PATH_MAX + 1]; |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 166 | memcpy(buf, self->str, self->len); |
| 167 | FRESULT res = f_getcwd(&self->fatfs, buf + self->len, sizeof(buf) - self->len); |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 168 | if (res != FR_OK) { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 169 | mp_raise_OSError(fresult_to_errno_table[res]); |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 170 | } |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 171 | // remove trailing / if in root dir, because we prepended the mount point |
| 172 | size_t l = strlen(buf); |
| 173 | if (res == FR_OK && buf[l - 1] == '/') { |
| 174 | buf[l - 1] = 0; |
| 175 | } |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 176 | return mp_obj_new_str(buf, strlen(buf), false); |
| 177 | } |
Paul Sokolovsky | ee5e3f6 | 2016-05-29 18:52:41 +0300 | [diff] [blame] | 178 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 179 | |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 180 | // Checks for path equality, ignoring trailing slashes: |
| 181 | // path_equal(/, /) -> true |
| 182 | // second argument must be in canonical form (meaning no trailing slash, unless it's just /) |
| 183 | STATIC bool path_equal(const char *path, const char *path_canonical) { |
| 184 | while (*path_canonical != '\0' && *path == *path_canonical) { |
| 185 | ++path; |
| 186 | ++path_canonical; |
| 187 | } |
| 188 | if (*path_canonical != '\0') { |
| 189 | return false; |
| 190 | } |
| 191 | while (*path == '/') { |
| 192 | ++path; |
| 193 | } |
| 194 | return *path == '\0'; |
| 195 | } |
| 196 | |
| 197 | /// \function stat(path) |
| 198 | /// Get the status of a file or directory. |
| 199 | STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 200 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 201 | const char *path = mp_obj_str_get_str(path_in); |
| 202 | |
| 203 | FILINFO fno; |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 204 | FRESULT res; |
| 205 | |
| 206 | if (path_equal(path, "/")) { |
| 207 | // stat root directory |
| 208 | fno.fsize = 0; |
Robert HH | 23067a1 | 2016-06-16 18:17:59 +0200 | [diff] [blame] | 209 | fno.fdate = 0x2821; // Jan 1, 2000 |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 210 | fno.ftime = 0; |
| 211 | fno.fattrib = AM_DIR; |
| 212 | } else { |
| 213 | res = FR_NO_PATH; |
| 214 | for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) { |
| 215 | fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i]; |
| 216 | if (vfs != NULL && path_equal(path, vfs->str)) { |
| 217 | // stat mounted device directory |
| 218 | fno.fsize = 0; |
Robert HH | 23067a1 | 2016-06-16 18:17:59 +0200 | [diff] [blame] | 219 | fno.fdate = 0x2821; // Jan 1, 2000 |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 220 | fno.ftime = 0; |
| 221 | fno.fattrib = AM_DIR; |
| 222 | res = FR_OK; |
| 223 | } |
| 224 | } |
| 225 | if (res == FR_NO_PATH) { |
| 226 | // stat normal file |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 227 | res = f_stat(&self->fatfs, path, &fno); |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 228 | } |
| 229 | if (res != FR_OK) { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 230 | mp_raise_OSError(fresult_to_errno_table[res]); |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 231 | } |
| 232 | } |
| 233 | |
| 234 | mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); |
| 235 | mp_int_t mode = 0; |
| 236 | if (fno.fattrib & AM_DIR) { |
| 237 | mode |= 0x4000; // stat.S_IFDIR |
| 238 | } else { |
| 239 | mode |= 0x8000; // stat.S_IFREG |
| 240 | } |
| 241 | mp_int_t seconds = timeutils_seconds_since_2000( |
| 242 | 1980 + ((fno.fdate >> 9) & 0x7f), |
| 243 | (fno.fdate >> 5) & 0x0f, |
| 244 | fno.fdate & 0x1f, |
| 245 | (fno.ftime >> 11) & 0x1f, |
| 246 | (fno.ftime >> 5) & 0x3f, |
| 247 | 2 * (fno.ftime & 0x1f) |
| 248 | ); |
| 249 | t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode |
| 250 | t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino |
| 251 | t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev |
| 252 | t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink |
| 253 | t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid |
| 254 | t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid |
| 255 | t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size |
| 256 | t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime |
| 257 | t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime |
| 258 | t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime |
| 259 | |
| 260 | return MP_OBJ_FROM_PTR(t); |
| 261 | } |
| 262 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat); |
| 263 | |
Alex March | dcf14c1 | 2016-09-12 18:13:44 +0100 | [diff] [blame] | 264 | // Get the status of a VFS. |
| 265 | STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 266 | mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); |
| 267 | (void)path_in; |
Alex March | dcf14c1 | 2016-09-12 18:13:44 +0100 | [diff] [blame] | 268 | |
Alex March | dcf14c1 | 2016-09-12 18:13:44 +0100 | [diff] [blame] | 269 | DWORD nclst; |
Damien George | f5f4cda | 2016-06-01 17:00:28 +0100 | [diff] [blame^] | 270 | FATFS *fatfs = &self->fatfs; |
| 271 | FRESULT res = f_getfree(fatfs, &nclst); |
Alex March | dcf14c1 | 2016-09-12 18:13:44 +0100 | [diff] [blame] | 272 | if (FR_OK != res) { |
Damien George | 620c4c3 | 2016-10-07 13:44:55 +1100 | [diff] [blame] | 273 | mp_raise_OSError(fresult_to_errno_table[res]); |
Alex March | dcf14c1 | 2016-09-12 18:13:44 +0100 | [diff] [blame] | 274 | } |
| 275 | |
| 276 | mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); |
| 277 | |
| 278 | t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * fatfs->ssize); // f_bsize |
| 279 | t->items[1] = t->items[0]; // f_frsize |
| 280 | t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2) * fatfs->csize); // f_blocks |
| 281 | t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree |
| 282 | t->items[4] = t->items[3]; // f_bavail |
| 283 | t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files |
| 284 | t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree |
| 285 | t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail |
| 286 | t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags |
| 287 | t->items[9] = MP_OBJ_NEW_SMALL_INT(_MAX_LFN); // f_namemax |
| 288 | |
| 289 | return MP_OBJ_FROM_PTR(t); |
| 290 | } |
| 291 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs); |
| 292 | |
Radomir Dopieralski | d29ca28 | 2016-08-22 16:10:34 +0200 | [diff] [blame] | 293 | // Unmount the filesystem |
| 294 | STATIC mp_obj_t fat_vfs_umount(mp_obj_t vfs_in) { |
| 295 | fatfs_umount(((fs_user_mount_t *)vfs_in)->readblocks[1]); |
| 296 | return mp_const_none; |
| 297 | } |
| 298 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, fat_vfs_umount); |
| 299 | |
Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 300 | STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { |
| 301 | { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) }, |
| 302 | { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) }, |
Paul Sokolovsky | cd6d189 | 2016-02-28 17:17:24 +0200 | [diff] [blame] | 303 | { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) }, |
Paul Sokolovsky | bbe832a | 2016-02-29 00:02:50 +0200 | [diff] [blame] | 304 | { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) }, |
Paul Sokolovsky | 0a6f599 | 2016-07-16 03:46:42 +0300 | [diff] [blame] | 305 | { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) }, |
Paul Sokolovsky | f12146c | 2016-05-29 18:17:00 +0300 | [diff] [blame] | 306 | { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) }, |
Paul Sokolovsky | cac6c97 | 2016-05-29 18:23:59 +0300 | [diff] [blame] | 307 | { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) }, |
Paul Sokolovsky | 19749db | 2016-02-28 20:30:07 +0200 | [diff] [blame] | 308 | { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) }, |
Paul Sokolovsky | e082183 | 2016-02-29 01:22:38 +0200 | [diff] [blame] | 309 | { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) }, |
Robert HH | ee009d7 | 2016-05-30 21:09:20 +0200 | [diff] [blame] | 310 | { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) }, |
Alex March | dcf14c1 | 2016-09-12 18:13:44 +0100 | [diff] [blame] | 311 | { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) }, |
Radomir Dopieralski | d29ca28 | 2016-08-22 16:10:34 +0200 | [diff] [blame] | 312 | { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, |
Paul Sokolovsky | e9be6a3 | 2016-02-13 22:51:21 +0200 | [diff] [blame] | 313 | }; |
| 314 | STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); |
| 315 | |
| 316 | const mp_obj_type_t mp_fat_vfs_type = { |
| 317 | { &mp_type_type }, |
| 318 | .name = MP_QSTR_VfsFat, |
| 319 | .make_new = fat_vfs_make_new, |
| 320 | .locals_dict = (mp_obj_dict_t*)&fat_vfs_locals_dict, |
| 321 | }; |
| 322 | |
| 323 | #endif // MICROPY_VFS_FAT |