[examples] Stream based filelister daemon implementation;
This commit is contained in:
		
							parent
							
								
									6534dda8a0
								
							
						
					
					
						commit
						f0c6a641ad
					
				@ -46,4 +46,6 @@
 | 
			
		||||
#define FREE(x) { if (x) { free(x); x = NULL; } }
 | 
			
		||||
#define MAX_STREAMS INT_MAX
 | 
			
		||||
 | 
			
		||||
#define DIRLIST_ID  1
 | 
			
		||||
 | 
			
		||||
#endif /*__SXMP_EXAMPLES_FILELIST_H__*/
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user