_p9dir.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
_p9dir.c (4733B)
---
     1 #include 
     2 #define NOPLAN9DEFINES
     3 #include 
     4 #include 
     5 #include 
     6 #include 
     7 #include 
     8 #include 
     9 
    10 #if defined(__APPLE__)
    11 #define _HAVESTGEN
    12 #include 
    13 static vlong
    14 disksize(int fd, struct stat *st)
    15 {
    16         u64int bc;
    17         u32int bs;
    18 
    19         bs = 0;
    20         bc = 0;
    21         ioctl(fd, DKIOCGETBLOCKSIZE, &bs);
    22         ioctl(fd, DKIOCGETBLOCKCOUNT, &bc);
    23         if(bs >0 && bc > 0)
    24                 return bc*bs;
    25         return 0;
    26 }
    27 
    28 #elif defined(__FreeBSD__)
    29 #define _HAVESTGEN
    30 #include 
    31 #include 
    32 #include 
    33 static vlong
    34 disksize(int fd, struct stat *st)
    35 {
    36         off_t mediasize;
    37         
    38         if(ioctl(fd, DIOCGMEDIASIZE, &mediasize) >= 0)
    39                 return mediasize;
    40         return 0;
    41 }
    42 
    43 #elif defined(__OpenBSD__)
    44 #define _HAVESTGEN
    45 #include 
    46 #include 
    47 #include 
    48 static vlong
    49 disksize(int fd, struct stat *st)
    50 {
    51         struct disklabel lab;
    52         int n;
    53 
    54         if(!S_ISCHR(st->st_mode))
    55                 return 0;
    56         if(ioctl(fd, DIOCGDINFO, &lab) < 0)
    57                 return 0;
    58         n = minor(st->st_rdev)&7;
    59         if(n >= lab.d_npartitions)
    60                 return 0;
    61         return (vlong)lab.d_partitions[n].p_size * lab.d_secsize;
    62 }
    63 
    64 #elif defined(__linux__)
    65 #include 
    66 #include 
    67 #include 
    68 #undef major
    69 #define major(dev) ((int)(((dev) >> 8) & 0xff))
    70 static vlong
    71 disksize(int fd, struct stat *st)
    72 {
    73         u64int u64;
    74         long l;
    75         struct hd_geometry geo;
    76 
    77         memset(&geo, 0, sizeof geo);
    78         l = 0;
    79         u64 = 0;
    80 #ifdef BLKGETSIZE64
    81         if(ioctl(fd, BLKGETSIZE64, &u64) >= 0)
    82                 return u64;
    83 #endif
    84         if(ioctl(fd, BLKGETSIZE, &l) >= 0)
    85                 return l*512;
    86         if(ioctl(fd, HDIO_GETGEO, &geo) >= 0)
    87                 return (vlong)geo.heads*geo.sectors*geo.cylinders*512;
    88         return 0;
    89 }
    90 
    91 #else
    92 static vlong
    93 disksize(int fd, struct stat *st)
    94 {
    95         return 0;
    96 }
    97 #endif
    98 
    99 int _p9usepwlibrary = 1;
   100 /*
   101  * Caching the last group and passwd looked up is
   102  * a significant win (stupidly enough) on most systems.
   103  * It's not safe for threaded programs, but neither is using
   104  * getpwnam in the first place, so I'm not too worried.
   105  */
   106 int
   107 _p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr)
   108 {
   109         char *s;
   110         char tmp[20];
   111         static struct group *g;
   112         static struct passwd *p;
   113         static int gid, uid;
   114         int sz, fd;
   115 
   116         fd = -1;
   117         USED(fd);
   118         sz = 0;
   119         if(d)
   120                 memset(d, 0, sizeof *d);
   121 
   122         /* name */
   123         s = strrchr(name, '/');
   124         if(s)
   125                 s++;
   126         if(!s || !*s)
   127                 s = name;
   128         if(*s == '/')
   129                 s++;
   130         if(*s == 0)
   131                 s = "/";
   132         if(d){
   133                 if(*str + strlen(s)+1 > estr)
   134                         d->name = "oops";
   135                 else{
   136                         strcpy(*str, s);
   137                         d->name = *str;
   138                         *str += strlen(*str)+1;
   139                 }
   140         }
   141         sz += strlen(s)+1;
   142 
   143         /* user */
   144         if(p && st->st_uid == uid && p->pw_uid == uid)
   145                 ;
   146         else if(_p9usepwlibrary){
   147                 p = getpwuid(st->st_uid);
   148                 uid = st->st_uid;
   149         }
   150         if(p == nil || st->st_uid != uid || p->pw_uid != uid){
   151                 snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
   152                 s = tmp;
   153         }else
   154                 s = p->pw_name;
   155         sz += strlen(s)+1;
   156         if(d){
   157                 if(*str+strlen(s)+1 > estr)
   158                         d->uid = "oops";        
   159                 else{
   160                         strcpy(*str, s);
   161                         d->uid = *str;
   162                         *str += strlen(*str)+1;
   163                 }
   164         }
   165 
   166         /* group */
   167         if(g && st->st_gid == gid && g->gr_gid == gid)
   168                 ;
   169         else if(_p9usepwlibrary){
   170                 g = getgrgid(st->st_gid);
   171                 gid = st->st_gid;
   172         }
   173         if(g == nil || st->st_gid != gid || g->gr_gid != gid){
   174                 snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
   175                 s = tmp;
   176         }else
   177                 s = g->gr_name;
   178         sz += strlen(s)+1;
   179         if(d){
   180                 if(*str + strlen(s)+1 > estr)
   181                         d->gid = "oops";        
   182                 else{
   183                         strcpy(*str, s);
   184                         d->gid = *str;
   185                         *str += strlen(*str)+1;
   186                 }
   187         }
   188 
   189         if(d){
   190                 d->type = 'M';
   191 
   192                 d->muid = "";
   193                 d->qid.path = st->st_ino;
   194                 /*
   195                  * do not include st->st_dev in path, because
   196                  * automounters give the same file system different
   197                  * st_dev values for successive mounts, causing
   198                  * spurious write warnings in acme and sam.
   199                 d->qid.path |= (uvlong)st->st_dev<<32;
   200                  */
   201 #ifdef _HAVESTGEN
   202                 d->qid.vers = st->st_gen;
   203 #endif
   204                 if(d->qid.vers == 0)
   205                         d->qid.vers = st->st_mtime + st->st_ctime;
   206                 d->mode = st->st_mode&0777;
   207                 d->atime = st->st_atime;
   208                 d->mtime = st->st_mtime;
   209                 d->length = st->st_size;
   210 
   211                 if(S_ISLNK(lst->st_mode)){        /* yes, lst not st */
   212                         d->mode |= DMSYMLINK;
   213                         d->length = lst->st_size;
   214                 }
   215                 else if(S_ISDIR(st->st_mode)){
   216                         d->length = 0;
   217                         d->mode |= DMDIR;
   218                         d->qid.type = QTDIR;
   219                 }
   220                 else if(S_ISFIFO(st->st_mode))
   221                         d->mode |= DMNAMEDPIPE;
   222                 else if(S_ISSOCK(st->st_mode))
   223                         d->mode |= DMSOCKET;
   224                 else if(S_ISBLK(st->st_mode)){
   225                         d->mode |= DMDEVICE;
   226                         d->qid.path = ('b'<<16)|st->st_rdev;
   227                 }
   228                 else if(S_ISCHR(st->st_mode)){
   229                         d->mode |= DMDEVICE;
   230                         d->qid.path = ('c'<<16)|st->st_rdev;
   231                 }
   232                 /* fetch real size for disks */
   233                 if(S_ISBLK(lst->st_mode) || S_ISCHR(lst->st_mode)){
   234                         if((fd = open(name, O_RDONLY)) >= 0){
   235                                 d->length = disksize(fd, st);
   236                                 close(fd);
   237                         }
   238                 }
   239         }
   240 
   241         return sz;
   242 }
   243