instow

:)
git clone https://git.sr.ht/~ashymad/instow
Log | Files | Refs | LICENSE

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 }