|
|
|
@ -54,6 +54,7 @@
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
|
|
#include <tdata/usrtc.h>
|
|
|
|
|
#include <tdata/list.h>
|
|
|
|
|
#include <sexpr/sexp.h>
|
|
|
|
|
#include <sxmp/limits.h>
|
|
|
|
|
#include <sxmp/sxmp.h>
|
|
|
|
@ -119,6 +120,109 @@ static int __ping(void *m, sexp_t *sx)
|
|
|
|
|
return sxmsg_return((sxmsg_t*)m, SXE_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* dir listing stream */
|
|
|
|
|
typedef struct __dirlist_type {
|
|
|
|
|
DIR *dp;
|
|
|
|
|
struct dirent dent;
|
|
|
|
|
struct dirent *dres;
|
|
|
|
|
} dirlist_t;
|
|
|
|
|
|
|
|
|
|
static int dirlist_open(sxlink_t *link, struct sxstream_opened *stream,
|
|
|
|
|
const char *dirname)
|
|
|
|
|
{
|
|
|
|
|
dirlist_t *pslist = malloc(sizeof(dirlist_t));
|
|
|
|
|
|
|
|
|
|
if(!pslist) return SXE_ENOMEM;
|
|
|
|
|
else memset(pslist, 0, sizeof(dirlist_t));
|
|
|
|
|
|
|
|
|
|
if(!(pslist->dp = opendir(dirname ? dirname : "./"))) {
|
|
|
|
|
free(pslist);
|
|
|
|
|
return SXE_FAILED;
|
|
|
|
|
} else sxstream_opened_setpriv(stream, pslist);
|
|
|
|
|
|
|
|
|
|
return SXE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int dirlist_close(struct sxstream_opened *stream)
|
|
|
|
|
{
|
|
|
|
|
dirlist_t *pslist = sxstream_opened_getpriv(stream);
|
|
|
|
|
list_head_t *llist = sxstream_opened_getelist(stream);
|
|
|
|
|
|
|
|
|
|
if(!pslist) return SXE_FAILED;
|
|
|
|
|
if(llist) sxstream_generic_slist_free(llist);
|
|
|
|
|
|
|
|
|
|
/* close dir and free strcuture */
|
|
|
|
|
if(pslist->dp) closedir(pslist->dp);
|
|
|
|
|
free(pslist);
|
|
|
|
|
|
|
|
|
|
return SXE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline const char *dump_type(struct dirent *d)
|
|
|
|
|
{
|
|
|
|
|
if(!d) return "nil";
|
|
|
|
|
|
|
|
|
|
switch(d->d_type) {
|
|
|
|
|
case DT_REG: return "regular";
|
|
|
|
|
case DT_DIR: return "directory";
|
|
|
|
|
case DT_BLK: return "block";
|
|
|
|
|
case DT_CHR: return "char";
|
|
|
|
|
case DT_FIFO: return "fifo";
|
|
|
|
|
case DT_LNK: return "link";
|
|
|
|
|
case DT_UNKNOWN: return "unknown";
|
|
|
|
|
default: return "another";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "nil";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static size_t dirlist_read(struct sxstream_opened *stream, size_t sz, uint64_t off,
|
|
|
|
|
list_head_t **rlist)
|
|
|
|
|
{
|
|
|
|
|
dirlist_t *pslist = sxstream_opened_getpriv(stream);
|
|
|
|
|
list_head_t *llist_prev = sxstream_opened_getelist(stream);
|
|
|
|
|
list_head_t *llist_new = NULL;
|
|
|
|
|
|
|
|
|
|
if(!pslist || !llist_new) return -1;
|
|
|
|
|
|
|
|
|
|
/* read and fill new list */
|
|
|
|
|
if(readdir_r(pslist->dp, &(pslist->dent), &(pslist->dres)))
|
|
|
|
|
return -1;
|
|
|
|
|
/* if finished return 0 */
|
|
|
|
|
if(!pslist->dres) return 0;
|
|
|
|
|
/* allocate a new */
|
|
|
|
|
if(!(llist_new = sxstream_generic_slist_alloc())) return -1;
|
|
|
|
|
else { /* fill this list */
|
|
|
|
|
if(sxstream_generic_slist_additem(llist_new, pslist->dres->d_name)) {
|
|
|
|
|
__fail:
|
|
|
|
|
sxstream_generic_slist_free(llist_new);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(sxstream_generic_slist_additem(llist_new, dump_type(pslist->dres)))
|
|
|
|
|
goto __fail;
|
|
|
|
|
}
|
|
|
|
|
/* otherwise destroy last list */
|
|
|
|
|
sxstream_generic_slist_free(llist_prev);
|
|
|
|
|
*rlist = llist_new; /* assign new list */
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct sxstream_ops dirlist_ops = {
|
|
|
|
|
.s_open = dirlist_open,
|
|
|
|
|
.s_close = dirlist_close,
|
|
|
|
|
.s_eread = dirlist_read,
|
|
|
|
|
.s_ewrite = NULL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct sxstream_description dirlist_stream = {
|
|
|
|
|
.stid = DIRLIST_ID,
|
|
|
|
|
.pcid = READONLY_CHANNEL,
|
|
|
|
|
.type = 0, /* just a simple one */
|
|
|
|
|
.flags = SXE_O_READ | SXE_O_TRUNC,
|
|
|
|
|
.ops = &dirlist_ops,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* command line options helpers */
|
|
|
|
|
static void __help_print(FILE *fso, const char *fmtname)
|
|
|
|
|
{
|
|
|
|
@ -252,7 +356,6 @@ int main(int argc, char **argv)
|
|
|
|
|
/* ok, let's add stream functions */
|
|
|
|
|
opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "ping", __ping);
|
|
|
|
|
if(opt) {
|
|
|
|
|
__fail:
|
|
|
|
|
fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n");
|
|
|
|
|
return opt;
|
|
|
|
|
}
|
|
|
|
@ -260,6 +363,9 @@ int main(int argc, char **argv)
|
|
|
|
|
/* ok, setup it */
|
|
|
|
|
sxhub_set_rpcvalidator(sxmphub, __rettlist);
|
|
|
|
|
|
|
|
|
|
/* setup our stream */
|
|
|
|
|
sxhub_stream_register(sxmphub, &dirlist_stream);
|
|
|
|
|
|
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
|
|
/* now we're ready to run the listen process */
|
|
|
|
|