libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

ixpc.c (6554B)


      1 /* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #define IXP_NO_P9_
      5 #define IXP_P9_STRUCTS
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <time.h>
     10 #include <unistd.h>
     11 #include <ixp_local.h>
     12 
     13 /* Temporary */
     14 #define fatal(...) ixp_eprint("ixpc: fatal: " __VA_ARGS__); \
     15 
     16 static IxpClient *client;
     17 
     18 static void
     19 usage(void) {
     20 	fprintf(stderr,
     21 		   "usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | write | append} <file>\n"
     22 		   "       %1$s [-a <address>] xwrite <file> <data>\n"
     23 		   "       %1$s -v\n", argv0);
     24 	exit(1);
     25 }
     26 
     27 /* Utility Functions */
     28 static void
     29 write_data(IxpCFid *fid, char *name) {
     30 	void *buf;
     31 	uint len;
     32 
     33 	buf = emalloc(fid->iounit);;
     34 	do {
     35 		len = read(0, buf, fid->iounit);
     36 		if(len >= 0 && ixp_write(fid, buf, len) != len)
     37 			fatal("cannot write file '%s': %s\n", name, ixp_errbuf());
     38 	} while(len > 0);
     39 
     40 	free(buf);
     41 }
     42 
     43 static int
     44 comp_stat(const void *s1, const void *s2) {
     45 	Stat *st1, *st2;
     46 
     47 	st1 = (Stat*)s1;
     48 	st2 = (Stat*)s2;
     49 	return strcmp(st1->name, st2->name);
     50 }
     51 
     52 static void
     53 setrwx(long m, char *s) {
     54 	static char *modes[] = {
     55 		"---", "--x", "-w-",
     56 		"-wx", "r--", "r-x",
     57 		"rw-", "rwx",
     58 	};
     59 	strncpy(s, modes[m], 3);
     60 }
     61 
     62 static char *
     63 str_of_mode(uint mode) {
     64 	static char buf[16];
     65 
     66 	buf[0]='-';
     67 	if(mode & P9_DMDIR)
     68 		buf[0]='d';
     69 	buf[1]='-';
     70 	setrwx((mode >> 6) & 7, &buf[2]);
     71 	setrwx((mode >> 3) & 7, &buf[5]);
     72 	setrwx((mode >> 0) & 7, &buf[8]);
     73 	buf[11] = 0;
     74 	return buf;
     75 }
     76 
     77 static char *
     78 str_of_time(uint val) {
     79 	static char buf[32];
     80 
     81 	ctime_r((time_t*)&val, buf);
     82 	buf[strlen(buf) - 1] = '\0';
     83 	return buf;
     84 }
     85 
     86 static void
     87 print_stat(Stat *s, int details) {
     88 	if(details)
     89 		fprintf(stdout, "%s %s %s %5llu %s %s\n", str_of_mode(s->mode),
     90 				s->uid, s->gid, s->length, str_of_time(s->mtime), s->name);
     91 	else {
     92 		if((s->mode&P9_DMDIR) && strcmp(s->name, "/"))
     93 			fprintf(stdout, "%s/\n", s->name);
     94 		else
     95 			fprintf(stdout, "%s\n", s->name);
     96 	}
     97 }
     98 
     99 /* Service Functions */
    100 static int
    101 xappend(int argc, char *argv[]) {
    102 	IxpCFid *fid;
    103 	IxpStat *stat;
    104 	char *file;
    105 
    106 	ARGBEGIN{
    107 	default:
    108 		usage();
    109 	}ARGEND;
    110 
    111 	file = EARGF(usage());
    112 	fid = ixp_open(client, file, P9_OWRITE);
    113 	if(fid == nil)
    114 		fatal("Can't open file '%s': %s\n", file, ixp_errbuf());
    115 	
    116 	stat = ixp_stat(client, file);
    117 	fid->offset = stat->length;
    118 	ixp_freestat(stat);
    119 	free(stat);
    120 	write_data(fid, file);
    121 	return 0;
    122 }
    123 
    124 static int
    125 xwrite(int argc, char *argv[]) {
    126 	IxpCFid *fid;
    127 	char *file;
    128 
    129 	ARGBEGIN{
    130 	default:
    131 		usage();
    132 	}ARGEND;
    133 
    134 	file = EARGF(usage());
    135 	fid = ixp_open(client, file, P9_OWRITE);
    136 	if(fid == nil)
    137 		fatal("Can't open file '%s': %s\n", file, ixp_errbuf());
    138 
    139 	write_data(fid, file);
    140 	return 0;
    141 }
    142 
    143 static int
    144 xawrite(int argc, char *argv[]) {
    145 	IxpCFid *fid;
    146 	char *file, *buf, *arg;
    147 	int nbuf, mbuf, len;
    148 
    149 	ARGBEGIN{
    150 	default:
    151 		usage();
    152 	}ARGEND;
    153 
    154 	file = EARGF(usage());
    155 	fid = ixp_open(client, file, P9_OWRITE);
    156 	if(fid == nil)
    157 		fatal("Can't open file '%s': %s\n", file, ixp_errbuf());
    158 
    159 	nbuf = 0;
    160 	mbuf = 128;
    161 	buf = emalloc(mbuf);
    162 	while(argc) {
    163 		arg = ARGF();
    164 		len = strlen(arg);
    165 		if(nbuf + len > mbuf) {
    166 			mbuf <<= 1;
    167 			buf = ixp_erealloc(buf, mbuf);
    168 		}
    169 		memcpy(buf+nbuf, arg, len);
    170 		nbuf += len;
    171 		if(argc)
    172 			buf[nbuf++] = ' ';
    173 	}
    174 
    175 	if(ixp_write(fid, buf, nbuf) == -1)
    176 		fatal("cannot write file '%s': %s\n", file, ixp_errbuf());
    177 	return 0;
    178 }
    179 
    180 static int
    181 xcreate(int argc, char *argv[]) {
    182 	IxpCFid *fid;
    183 	char *file;
    184 
    185 	ARGBEGIN{
    186 	default:
    187 		usage();
    188 	}ARGEND;
    189 
    190 	file = EARGF(usage());
    191 	fid = ixp_create(client, file, 0777, P9_OWRITE);
    192 	if(fid == nil)
    193 		fatal("Can't create file '%s': %s\n", file, ixp_errbuf());
    194 
    195 	if((fid->qid.type&P9_DMDIR) == 0)
    196 		write_data(fid, file);
    197 
    198 	return 0;
    199 }
    200 
    201 static int
    202 xremove(int argc, char *argv[]) {
    203 	char *file;
    204 
    205 	ARGBEGIN{
    206 	default:
    207 		usage();
    208 	}ARGEND;
    209 
    210 	file = EARGF(usage());
    211 	if(ixp_remove(client, file) == 0)
    212 		fatal("Can't remove file '%s': %s\n", file, ixp_errbuf());
    213 	return 0;
    214 }
    215 
    216 static int
    217 xread(int argc, char *argv[]) {
    218 	IxpCFid *fid;
    219 	char *file, *buf;
    220 	int count;
    221 
    222 	ARGBEGIN{
    223 	default:
    224 		usage();
    225 	}ARGEND;
    226 
    227 	file = EARGF(usage());
    228 	fid = ixp_open(client, file, P9_OREAD);
    229 	if(fid == nil)
    230 		fatal("Can't open file '%s': %s\n", file, ixp_errbuf());
    231 
    232 	buf = emalloc(fid->iounit);
    233 	while((count = ixp_read(fid, buf, fid->iounit)) > 0)
    234 		write(1, buf, count);
    235 
    236 	if(count == -1)
    237 		fatal("cannot read file/directory '%s': %s\n", file, ixp_errbuf());
    238 
    239 	return 0;
    240 }
    241 
    242 static int
    243 xls(int argc, char *argv[]) {
    244 	IxpMsg m;
    245 	Stat *stat;
    246 	IxpCFid *fid;
    247 	char *file, *buf;
    248 	int lflag, dflag, count, nstat, mstat, i;
    249 
    250 	lflag = dflag = 0;
    251 
    252 	ARGBEGIN{
    253 	case 'l':
    254 		lflag++;
    255 		break;
    256 	case 'd':
    257 		dflag++;
    258 		break;
    259 	default:
    260 		usage();
    261 	}ARGEND;
    262 
    263 	file = EARGF(usage());
    264 
    265 	stat = ixp_stat(client, file);
    266 	if(stat == nil)
    267 		fatal("cannot stat file '%s': %s\n", file, ixp_errbuf());
    268 
    269 	if(dflag || (stat->mode&P9_DMDIR) == 0) {
    270 		print_stat(stat, lflag);
    271 		ixp_freestat(stat);
    272 		return 0;
    273 	}
    274 	ixp_freestat(stat);
    275 
    276 	fid = ixp_open(client, file, P9_OREAD);
    277 	if(fid == nil)
    278 		fatal("Can't open file '%s': %s\n", file, ixp_errbuf());
    279 
    280 	nstat = 0;
    281 	mstat = 16;
    282 	stat = emalloc(sizeof(*stat) * mstat);
    283 	buf = emalloc(fid->iounit);
    284 	while((count = ixp_read(fid, buf, fid->iounit)) > 0) {
    285 		m = ixp_message(buf, count, MsgUnpack);
    286 		while(m.pos < m.end) {
    287 			if(nstat == mstat) {
    288 				mstat <<= 1;
    289 				stat = ixp_erealloc(stat, sizeof(*stat) * mstat);
    290 			}
    291 			ixp_pstat(&m, &stat[nstat++]);
    292 		}
    293 	}
    294 
    295 	qsort(stat, nstat, sizeof(*stat), comp_stat);
    296 	for(i = 0; i < nstat; i++) {
    297 		print_stat(&stat[i], lflag);
    298 		ixp_freestat(&stat[i]);
    299 	}
    300 	free(stat);
    301 
    302 	if(count == -1)
    303 		fatal("cannot read directory '%s': %s\n", file, ixp_errbuf());
    304 	return 0;
    305 }
    306 
    307 typedef struct exectab exectab;
    308 struct exectab {
    309 	char *cmd;
    310 	int (*fn)(int, char**);
    311 } etab[] = {
    312 	{"append", xappend},
    313 	{"write", xwrite},
    314 	{"xwrite", xawrite},
    315 	{"read", xread},
    316 	{"create", xcreate},
    317 	{"remove", xremove},
    318 	{"ls", xls},
    319 	{0, 0}
    320 };
    321 
    322 int
    323 main(int argc, char *argv[]) {
    324 	char *cmd, *address;
    325 	exectab *tab;
    326 	int ret;
    327 
    328 	address = getenv("IXP_ADDRESS");
    329 
    330 	ARGBEGIN{
    331 	case 'v':
    332 		printf("%s-" VERSION ", ©2007 Kris Maglione\n", argv0);
    333 		exit(0);
    334 	case 'a':
    335 		address = EARGF(usage());
    336 		break;
    337 	default:
    338 		usage();
    339 	}ARGEND;
    340 
    341 	cmd = EARGF(usage());
    342 
    343 	if(!address)
    344 		fatal("$IXP_ADDRESS not set\n");
    345 
    346 	client = ixp_mount(address);
    347 	if(client == nil)
    348 		fatal("%s\n", ixp_errbuf());
    349 
    350 	for(tab = etab; tab->cmd; tab++)
    351 		if(strcmp(cmd, tab->cmd) == 0) break;
    352 	if(tab->cmd == 0)
    353 		usage();
    354 
    355 	ret = tab->fn(argc, argv);
    356 
    357 	ixp_unmount(client);
    358 	return ret;
    359 }