|
|
|
@ -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 */
|
|
|
|
|