1 /* Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com>
2 * See LICENSE file for license details.
11 #include <9p-mixp/mixp.h>
12 #include <9p-mixp/err.h>
13 #include <9p-mixp/stat.h>
14 #include <9p-mixp/convert.h>
17 #define fatal(...) ixp_eprint("ixpc: fatal: " __VA_ARGS__); \
20 #define ARGBEGIN int _argi=0, _argtmp=0, _inargv=0; char *_argv=NULL; \
21 if(!argv0)argv0=ARGF(); _inargv=1; \
22 while(argc && argv[0][0] == '-') { \
23 _argi=1; _argv=*argv++; argc--; \
24 while(_argv[_argi]) switch(_argv[_argi++])
25 #define ARGEND }_inargv=0;USED(_argtmp);USED(_argv);USED(_argi)
26 #define ARGF() ((_inargv && _argv[_argi]) ? \
27 (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \
28 : ((argc > 0) ? (argc--, *argv++) : ((char*)0)))
29 #define EARGF(f) ((_inargv && _argv[_argi]) ? \
30 (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \
31 : ((argc > 0) ? (argc--, *argv++) : ((f), (char*)0)))
32 #define USED(x) if(x){}else
33 #define SET(x) ((x)=0)
35 static MIXP_CLIENT
*client
;
40 "usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | write} <file>\n"
41 " %1$s [-a <address>] xwrite <file> <data>\n"
46 /* Utility Functions */
48 write_data(MIXP_CFID
*fid
, char *name
) {
52 buf
= malloc(fid
->iounit
);;
54 len
= read(0, buf
, fid
->iounit
);
55 if(len
>= 0 && mixp_write(fid
, buf
, len
) != len
)
56 fatal("cannot write file '%s': %s\n", name
, mixp_errbuf());
63 comp_stat(const void *s1
, const void *s2
) {
68 return strcmp(st1
->name
, st2
->name
);
72 setrwx(long m
, char *s
) {
73 static char *modes
[] = {
78 strncpy(s
, modes
[m
], 3);
82 str_of_mode(unsigned int mode
) {
89 setrwx((mode
>> 6) & 7, &buf
[2]);
90 setrwx((mode
>> 3) & 7, &buf
[5]);
91 setrwx((mode
>> 0) & 7, &buf
[8]);
97 str_of_time(unsigned int val
) {
102 buf
[strlen(buf
) - 1] = '\0';
107 print_stat(MIXP_STAT
*s
, int details
) {
109 fprintf(stdout
, "%s %s %s %5llu %s %s\n", str_of_mode(s
->mode
),
110 s
->uid
, s
->gid
, s
->length
, str_of_time(s
->mtime
), s
->name
);
112 if((s
->mode
&P9_DMDIR
) && strcmp(s
->name
, "/"))
113 fprintf(stdout
, "%s/\n", s
->name
);
115 fprintf(stdout
, "%s\n", s
->name
);
119 /* Service Functions */
121 xwrite(int argc
, char *argv
[]) {
130 file
= EARGF(usage());
131 fid
= mixp_open(client
, file
, P9_OWRITE
);
133 fatal("Can't open file '%s': %s\n", file
, mixp_errbuf());
135 write_data(fid
, file
);
140 xawrite(int argc
, char *argv
[]) {
142 char *file
, *buf
, *arg
;
150 file
= EARGF(usage());
151 fid
= mixp_open(client
, file
, P9_OWRITE
);
153 fatal("Can't open file '%s': %s\n", file
, mixp_errbuf());
161 if(nbuf
+ len
> mbuf
) {
163 buf
= ixp_erealloc(buf
, mbuf
);
165 memcpy(buf
+nbuf
, arg
, len
);
171 if(mixp_write(fid
, buf
, nbuf
) == -1)
172 fatal("cannot write file '%s': %s\n", file
, mixp_errbuf());
177 xcreate(int argc
, char *argv
[]) {
186 file
= EARGF(usage());
187 fid
= mixp_create(client
, file
, 0777, P9_OWRITE
);
189 fatal("Can't create file '%s': %s\n", file
, mixp_errbuf());
191 if((fid
->qid
.type
&P9_DMDIR
) == 0)
192 write_data(fid
, file
);
198 xremove(int argc
, char *argv
[]) {
206 file
= EARGF(usage());
207 if(mixp_remove(client
, file
) == 0)
208 fatal("Can't remove file '%s': %s\n", file
, mixp_errbuf());
213 xread(int argc
, char *argv
[]) {
223 file
= EARGF(usage());
224 fid
= mixp_open(client
, file
, P9_OREAD
);
226 fatal("Can't open file '%s': %s\n", file
, mixp_errbuf());
228 buf
= malloc(fid
->iounit
);
229 while((count
= mixp_read(fid
, buf
, fid
->iounit
)) > 0)
230 write(1, buf
, count
);
233 fatal("cannot read file/directory '%s': %s\n", file
, mixp_errbuf());
239 xls(int argc
, char *argv
[]) {
244 int lflag
, dflag
, count
, nstat
, mstat
, i
;
259 file
= EARGF(usage());
261 stat
= mixp_stat(client
, file
);
263 fatal("cannot stat file '%s': %s\n", file
, mixp_errbuf());
265 if(dflag
|| (stat
->mode
&P9_DMDIR
) == 0) {
266 print_stat(stat
, lflag
);
267 mixp_stat_free(stat
);
270 mixp_stat_free(stat
);
272 fid
= mixp_open(client
, file
, P9_OREAD
);
274 fatal("Can't open file '%s': %s\n", file
, mixp_errbuf());
278 stat
= malloc(sizeof(*stat
) * mstat
);
279 buf
= malloc(fid
->iounit
);
280 while((count
= mixp_read(fid
, buf
, fid
->iounit
)) > 0) {
281 m
= mixp_message(buf
, count
, MsgUnpack
);
282 while(m
.pos
< m
.end
) {
285 stat
= ixp_erealloc(stat
, sizeof(*stat
) * mstat
);
287 mixp_pstat(&m
, &stat
[nstat
++]);
291 qsort(stat
, nstat
, sizeof(*stat
), comp_stat
);
292 for(i
= 0; i
< nstat
; i
++) {
293 print_stat(&stat
[i
], lflag
);
294 mixp_stat_free(&stat
[i
]);
299 fatal("cannot read directory '%s': %s\n", file
, mixp_errbuf());
303 typedef struct exectab exectab
;
306 int (*fn
)(int, char**);
318 main(int argc
, char *argv
[]) {
323 address
= getenv("IXP_ADDRESS");
327 printf("%s-" VERSION
", (C) 2007 Kris Maglione, 2008 Enrico Weigelt <weigelt@metux.de>\n", argv0
);
333 address
= EARGF(usage());
339 cmd
= EARGF(usage());
342 fatal("$IXP_ADDRESS not set\n");
344 MIXP_SERVER_ADDRESS
* addr
= mixp_srv_addr_parse(address
);
346 fatal("Could not parse address\n");
348 // printf("addr.hostname=\"%s\"\n", addr->hostname);
349 // printf("addr.port=\"%d\"\n", addr->port);
350 // printf("addr.path=\"%s\"\n", addr->path);
351 // printf("addr.proto=\"%d\"\n", addr->proto);
353 client
= mixp_mount_addr(addr
);
356 fatal("Could not mount: %s\n", mixp_errbuf());
358 for(tab
= etab
; tab
->cmd
; tab
++)
359 if(strcmp(cmd
, tab
->cmd
) == 0) break;
363 ret
= tab
->fn(argc
, argv
);
365 mixp_unmount(client
);