plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

_p9dir.c (4665B)


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