os.c (5286B)
1 #include "os.h" 2 3 static int32_t janet_perm_to_unix(mode_t m) { return (int32_t)m; } 4 5 static mode_t janet_perm_from_unix(int32_t x) { return (mode_t)x; } 6 7 static const uint8_t *janet_decode_mode(mode_t m) { 8 const char *str = "other"; 9 if (S_ISREG(m)) 10 str = "file"; 11 else if (S_ISDIR(m)) 12 str = "directory"; 13 else if (S_ISFIFO(m)) 14 str = "fifo"; 15 else if (S_ISBLK(m)) 16 str = "block"; 17 else if (S_ISSOCK(m)) 18 str = "socket"; 19 else if (S_ISLNK(m)) 20 str = "link"; 21 else if (S_ISCHR(m)) 22 str = "character"; 23 return janet_ckeyword(str); 24 } 25 26 static int32_t janet_decode_permissions(jmode_t mode) { 27 return (int32_t)(mode & 0777); 28 } 29 30 static int32_t os_parse_permstring(const uint8_t *perm) { 31 int32_t m = 0; 32 if (perm[0] == 'r') 33 m |= 0400; 34 if (perm[1] == 'w') 35 m |= 0200; 36 if (perm[2] == 'x') 37 m |= 0100; 38 if (perm[3] == 'r') 39 m |= 0040; 40 if (perm[4] == 'w') 41 m |= 0020; 42 if (perm[5] == 'x') 43 m |= 0010; 44 if (perm[6] == 'r') 45 m |= 0004; 46 if (perm[7] == 'w') 47 m |= 0002; 48 if (perm[8] == 'x') 49 m |= 0001; 50 return m; 51 } 52 53 static Janet os_make_permstring(int32_t permissions) { 54 uint8_t bytes[9] = {0}; 55 bytes[0] = (permissions & 0400) ? 'r' : '-'; 56 bytes[1] = (permissions & 0200) ? 'w' : '-'; 57 bytes[2] = (permissions & 0100) ? 'x' : '-'; 58 bytes[3] = (permissions & 0040) ? 'r' : '-'; 59 bytes[4] = (permissions & 0020) ? 'w' : '-'; 60 bytes[5] = (permissions & 0010) ? 'x' : '-'; 61 bytes[6] = (permissions & 0004) ? 'r' : '-'; 62 bytes[7] = (permissions & 0002) ? 'w' : '-'; 63 bytes[8] = (permissions & 0001) ? 'x' : '-'; 64 return janet_stringv(bytes, sizeof(bytes)); 65 } 66 67 static int32_t os_get_unix_mode(const Janet *argv, int32_t n) { 68 int32_t unix_mode; 69 if (janet_checkint(argv[n])) { 70 /* Integer mode */ 71 int32_t x = janet_unwrap_integer(argv[n]); 72 if (x < 0 || x > 0777) { 73 janet_panicf("bad slot #%d, expected integer in range [0, 8r777], got %v", 74 n, argv[n]); 75 } 76 unix_mode = x; 77 } else { 78 /* Bytes mode */ 79 JanetByteView bytes = janet_getbytes(argv, n); 80 if (bytes.len != 9) { 81 janet_panicf("bad slot #%d: expected byte sequence of length 9, got %v", 82 n, argv[n]); 83 } 84 unix_mode = os_parse_permstring(bytes.bytes); 85 } 86 return unix_mode; 87 } 88 89 jmode_t os_getmode(const Janet *argv, int32_t n) { 90 return janet_perm_from_unix(os_get_unix_mode(argv, n)); 91 } 92 93 /* Getters */ 94 static Janet os_stat_dev(const jstat_t *st) { 95 return janet_wrap_number(st->st_dev); 96 } 97 static Janet os_stat_inode(const jstat_t *st) { 98 return janet_wrap_number(st->st_ino); 99 } 100 static Janet os_stat_mode(const jstat_t *st) { 101 return janet_wrap_keyword(janet_decode_mode(st->st_mode)); 102 } 103 static Janet os_stat_int_permissions(const jstat_t *st) { 104 return janet_wrap_integer( 105 janet_perm_to_unix(janet_decode_permissions(st->st_mode))); 106 } 107 static Janet os_stat_permissions(const jstat_t *st) { 108 return os_make_permstring( 109 janet_perm_to_unix(janet_decode_permissions(st->st_mode))); 110 } 111 static Janet os_stat_uid(const jstat_t *st) { 112 return janet_wrap_number(st->st_uid); 113 } 114 static Janet os_stat_gid(const jstat_t *st) { 115 return janet_wrap_number(st->st_gid); 116 } 117 static Janet os_stat_nlink(const jstat_t *st) { 118 return janet_wrap_number(st->st_nlink); 119 } 120 static Janet os_stat_rdev(const jstat_t *st) { 121 return janet_wrap_number(st->st_rdev); 122 } 123 static Janet os_stat_size(const jstat_t *st) { 124 return janet_wrap_number(st->st_size); 125 } 126 static Janet os_stat_accessed(const jstat_t *st) { 127 return janet_wrap_number((double)st->st_atime); 128 } 129 static Janet os_stat_modified(const jstat_t *st) { 130 return janet_wrap_number((double)st->st_mtime); 131 } 132 static Janet os_stat_changed(const jstat_t *st) { 133 return janet_wrap_number((double)st->st_ctime); 134 } 135 static Janet os_stat_blocks(const jstat_t *st) { 136 return janet_wrap_number(st->st_blocks); 137 } 138 static Janet os_stat_blocksize(const jstat_t *st) { 139 return janet_wrap_number(st->st_blksize); 140 } 141 142 struct OsStatGetter { 143 const char *name; 144 Janet (*fn)(const jstat_t *st); 145 }; 146 147 const struct OsStatGetter os_stat_getters[] = { 148 {"dev", os_stat_dev}, 149 {"inode", os_stat_inode}, 150 {"mode", os_stat_mode}, 151 {"int-permissions", os_stat_int_permissions}, 152 {"permissions", os_stat_permissions}, 153 {"uid", os_stat_uid}, 154 {"gid", os_stat_gid}, 155 {"nlink", os_stat_nlink}, 156 {"rdev", os_stat_rdev}, 157 {"size", os_stat_size}, 158 {"blocks", os_stat_blocks}, 159 {"blocksize", os_stat_blocksize}, 160 {"accessed", os_stat_accessed}, 161 {"modified", os_stat_modified}, 162 {"changed", os_stat_changed}, 163 {NULL, NULL}}; 164 165 Janet stat2table(const jstat_t *st, const uint8_t *key) { 166 167 if (NULL == st) 168 return janet_wrap_nil(); 169 170 JanetTable *tab = janet_table(0); 171 172 if (NULL == key) { 173 /* Put results in table */ 174 for (const struct OsStatGetter *sg = os_stat_getters; sg->name != NULL; 175 sg++) { 176 janet_table_put(tab, janet_ckeywordv(sg->name), sg->fn(st)); 177 } 178 return janet_wrap_table(tab); 179 } else { 180 /* Get one result */ 181 for (const struct OsStatGetter *sg = os_stat_getters; sg->name != NULL; 182 sg++) { 183 if (janet_cstrcmp(key, sg->name)) 184 continue; 185 return sg->fn(st); 186 } 187 janet_panicf("unexpected keyword %v", janet_wrap_keyword(key)); 188 } 189 }