URI: 
       _p9dir.c - 9base - revived minimalist port of Plan 9 userland to Unix
  HTML git clone git://git.suckless.org/9base
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       _p9dir.c (4733B)
       ---
            1 #include <u.h>
            2 #define NOPLAN9DEFINES
            3 #include <libc.h>
            4 #include <sys/types.h>
            5 #include <sys/stat.h>
            6 #include <dirent.h>
            7 #include <pwd.h>
            8 #include <grp.h>
            9 
           10 #if defined(__APPLE__)
           11 #define _HAVESTGEN
           12 #include <sys/disk.h>
           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 <sys/disk.h>
           31 #include <sys/disklabel.h>
           32 #include <sys/ioctl.h>
           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 <sys/disklabel.h>
           46 #include <sys/ioctl.h>
           47 #include <sys/dkio.h>
           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 <linux/hdreg.h>
           66 #include <linux/fs.h>
           67 #include <sys/ioctl.h>
           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