[examples] Added stat function to the smpfd daemon;

v0.5.xx
Alexander Vdolainen 9 years ago
parent b6e1814d80
commit 7e35c61400

@ -4,15 +4,15 @@
* (c) Alexander Vdolainen 2013-2015 <avdolainen@gmail.com>
* (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
*
* libsxmp is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* libsxmp examples is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libsxmp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.";
@ -27,8 +27,9 @@
* This implements a simple client-server topology, to see
* more advanced technics check out other examples.
*
* NOTE(win32): don't have a time to test it or fix it to
* make it works on windows, if you can - u're welcome.
* NOTE(win32): win32 is not a platform for any serious,
* except the games maybe... well, this code contains linux
* stuff (not sure about other *nixes)
*/
#include <stdio.h>
@ -37,6 +38,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/select.h>
#include <sys/wait.h>
@ -44,21 +46,22 @@
#include <sys/resource.h>
#include <netdb.h>
#include <unistd.h>
#include <uuid/uuid.h>
#include <pwd.h>
#include <grp.h>
#include <execinfo.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdint.h>
#include <getopt.h>
#include <errno.h>
#include <uuid/uuid.h>
#include <tdata/usrtc.h>
#include <tdata/list.h>
#include <sexpr/sexp.h>
#include <sxmp/limits.h>
#include <sxmp/sxmp.h>
#include <pthread.h>
#include <stdint.h>
#include <getopt.h>
#include <errno.h>
#include "smpf.h"
#include "smpfd_defs.h"
#include "../config.h"
@ -73,6 +76,102 @@ static struct smpfd_ctx daemon_ctx;
*/
static usrtc_t *fulist;
/* misc functions */
static char *__humansize(struct stat *buf)
{
char *hsize = malloc(64);
int d = 0;
if(!hsize) return NULL;
if(buf->st_size < 10*1024) snprintf(hsize, 64, "%ld", buf->st_size);
else if(buf->st_size >= 10*1024 && buf->st_size < 1024*1024) { /* KiB */
d = buf->st_size % 1024;
if(!d) snprintf(hsize, 64, "%ldKiB", buf->st_size/1024);
else snprintf(hsize, 64, "%ld.%dKiB", buf->st_size/1024, d /= 102);
} else if(buf->st_size >= 1024*1024 && buf->st_size < 1024*1024*1024) { /* MiB */
d = buf->st_size % (1024*1024);
if(!d) snprintf(hsize, 64, "%ldMiB", buf->st_size/(1024*1024));
else snprintf(hsize, 64, "%ld.%dMiB", buf->st_size/(1024*1024), d /= 102);
} else { /* GiB */
d = buf->st_size % (1024*1024*1024);
if(!d) snprintf(hsize, 64, "%ldGiB", buf->st_size/(1024*1024*1024));
else snprintf(hsize, 64, "%ld.%dGiB", buf->st_size/(1024*1024*1024), d /= 102);
}
return hsize;
}
static char *__humanmode(struct stat *buf)
{
char *hmode = malloc(12);
char s = 0;
int i;
if(!hmode) return NULL;
memset(hmode, 0, 12);
for(i = 0; i < 10; i++) {
switch(i) {
case 0:
if(S_ISDIR(buf->st_mode)) s = 'd';
else if(S_ISCHR(buf->st_mode)) s = 'c';
else if(S_ISBLK(buf->st_mode)) s = 'b';
else if(S_ISFIFO(buf->st_mode)) s = 'f';
else if(S_ISLNK(buf->st_mode)) s = 'l';
else if(S_ISSOCK(buf->st_mode)) s = 's';
else s = '-';
break;
}
hmode[i] = s;
}
return hmode;
}
static char *__humanuser(struct stat *buf)
{
struct passwd pwd;
struct passwd *res;
char *pwdbuf, *huser;
size_t pwdlen;
if((pwdlen = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) pwdlen = 16384;
if(!(pwdbuf = malloc(pwdlen))) return NULL;
getpwuid_r(buf->st_uid, &pwd, pwdbuf, pwdlen, &res);
if(!res) {
if(!(huser = malloc(12))) goto __fini;
snprintf(huser, 12, "%d", buf->st_uid);
} else huser = strdup(pwd.pw_name);
__fini:
free(pwdbuf);
return huser;
}
static char *__humangroup(struct stat *buf)
{
struct group grp;
struct group *res;
char *pwdbuf, *hgroup;
size_t pwdlen;
if((pwdlen = sysconf(_SC_GETGR_R_SIZE_MAX)) == -1) pwdlen = 16384;
if(!(pwdbuf = malloc(pwdlen))) return NULL;
getgrgid_r(buf->st_gid, &grp, pwdbuf, pwdlen, &res);
if(!res) {
if(!(hgroup = malloc(12))) goto __fini;
snprintf(hgroup, 12, "%d", buf->st_gid);
} else hgroup = strdup(grp.gr_name);
__fini:
free(pwdbuf);
return hgroup;
}
/* ok, here we will define out sxmp specific functions */
/*
@ -211,6 +310,74 @@ static int __getcwd(void *m, sexp_t *sx)
return sxmsg_rreply(msg, rbuf_len);
}
static int __stat(void *m, sexp_t *sx)
{
sxmsg_t *msg = (sxmsg_t*)m;
sxlink_t *link = sxmsg_link(msg);
char *rbuf = sxmsg_rapidbuf(msg), *dirname = NULL, *odir = NULL;
char *hsize, *hmode, *huser, *hgroup;
sexp_t *isx;
size_t rbuf_len = 0;
int r = SXE_SUCCESS, idx, olen = 0, rc;
struct mp_session *session = (struct mp_session *)sxlink_getpriv(link);
struct stat statbuf;
SEXP_ITERATE_LIST(sx, isx, idx) {
if(isx->ty == SEXP_LIST) r = SXE_BADPROTO;
if(idx > 1) r = SXE_BADPROTO;
if(idx) dirname = isx->val;
}
if(r != SXE_SUCCESS || !dirname) goto __fail;
if(!strcmp(dirname, "./")) goto __fail;
if(!strlen(dirname) || !strcmp(dirname, ".")) goto __fail;
if(*dirname == '/') odir = strdup(dirname);
else {
olen = strlen(session->cwd) + strlen(dirname) + 2*sizeof(char);
odir = malloc(olen);
}
if(!odir) {
r = SXE_ENOMEM;
goto __fail;
}
if(olen) snprintf(odir, olen, "%s/%s", session->cwd, dirname);
if(normalize_path(odir)) r = SXE_FAILED;
else { /* take stat of the file */
rc = stat(odir, &statbuf);
if(rc) {
r = SXE_FAILED;
goto __fail;
}
/* make this human readable to reply for client */
hsize = __humansize(&statbuf);
hmode = __humanmode(&statbuf);
huser = __humanuser(&statbuf);
hgroup = __humangroup(&statbuf);
/* create a reply */
rbuf_len = snprintf(rbuf, MAX_RBBUF_LEN, "((:user %s)(:group %s)(:size %s)(:mode %s))",
huser, hgroup, hsize, hmode);
/* free */
if(odir) free(odir);
if(hsize) free(hsize);
if(hmode) free(hmode);
if(huser) free(huser);
if(hgroup) free(hgroup);
/* reply rapidly */
return sxmsg_rreply(msg, rbuf_len);
}
__fail:
if(odir) free(odir);
return sxmsg_return(msg, r);
}
/* stream, simple entry nonamed streams */
/* dir listing stream */
typedef struct __dirlist_type {
@ -474,7 +641,7 @@ int main(int argc, char **argv)
if(opt) goto __failaddrpc;
opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, GETCWD_CMD, __getcwd);
if(opt) goto __failaddrpc;
opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, STAT_CMD, __ping);
opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, STAT_CMD, __stat);
if(opt) goto __failaddrpc;
/* streams */

Loading…
Cancel
Save