2017-01-03 02:48:55 +00:00
|
|
|
/* radare - LGPL - Copyright 2013-2017 - pancake */
|
2014-05-22 09:25:58 +00:00
|
|
|
|
2014-02-18 03:03:07 +00:00
|
|
|
#include <r_core.h>
|
2015-04-02 13:30:21 +00:00
|
|
|
#include <errno.h>
|
2014-02-18 03:03:07 +00:00
|
|
|
|
2017-01-13 11:49:28 +00:00
|
|
|
#define FMT_NONE 0
|
2014-11-10 03:14:57 +00:00
|
|
|
#define FMT_RAW 1
|
|
|
|
#define FMT_JSON 2
|
|
|
|
|
2015-08-18 00:44:59 +00:00
|
|
|
static int needs_newline = 0;
|
|
|
|
|
2017-01-03 02:48:55 +00:00
|
|
|
static char *showfile(char *res, const int nth, const char *fpath, const char *name, int printfmt) {
|
2015-01-12 01:52:12 +00:00
|
|
|
#if __UNIX__
|
2014-05-22 09:25:58 +00:00
|
|
|
struct stat sb;
|
2015-01-12 01:52:12 +00:00
|
|
|
#endif
|
2014-11-10 03:14:57 +00:00
|
|
|
const char *n = fpath;
|
2015-01-14 01:53:34 +00:00
|
|
|
char *nn, *u_rwx = NULL;
|
2014-05-22 09:25:58 +00:00
|
|
|
int sz = r_file_size (n);
|
2017-01-03 02:48:55 +00:00
|
|
|
int perm, uid = 0, gid = 0;
|
2014-05-22 09:25:58 +00:00
|
|
|
int fch = '-';
|
2016-10-26 21:16:31 +00:00
|
|
|
if (!strncmp (fpath, "./", 2)) {
|
|
|
|
fpath = fpath + 2;
|
|
|
|
}
|
2017-01-03 02:48:55 +00:00
|
|
|
const bool isdir = r_file_is_directory (n);
|
|
|
|
if (isdir) {
|
2017-03-16 21:29:49 +00:00
|
|
|
nn = r_str_append (strdup (fpath), "/");
|
2014-05-22 09:25:58 +00:00
|
|
|
} else {
|
2014-11-10 03:14:57 +00:00
|
|
|
nn = strdup (fpath);
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
|
|
|
if (!*nn) {
|
|
|
|
free (nn);
|
2017-01-03 02:48:55 +00:00
|
|
|
return res;
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
|
|
|
perm = isdir? 0755: 0644;
|
2014-11-10 03:14:57 +00:00
|
|
|
if (!printfmt) {
|
2017-01-13 11:49:28 +00:00
|
|
|
needs_newline = ((nth + 1) % 4)? 1: 0;
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "%18s%s", nn, needs_newline? " ": "\n");
|
2014-05-26 22:09:17 +00:00
|
|
|
free (nn);
|
2017-01-03 02:48:55 +00:00
|
|
|
return res;
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
|
|
|
// TODO: escape non-printable chars in filenames
|
|
|
|
// TODO: Implement more real info in ls -l
|
|
|
|
// TODO: handle suid
|
|
|
|
#if __UNIX__
|
|
|
|
if (lstat (n, &sb) != -1) {
|
|
|
|
ut32 ifmt = sb.st_mode & S_IFMT;
|
|
|
|
uid = sb.st_uid;
|
|
|
|
gid = sb.st_gid;
|
|
|
|
perm = sb.st_mode & 0777;
|
2016-10-26 21:16:31 +00:00
|
|
|
if (!(u_rwx = strdup (r_str_rwx_i (perm >> 6)))) {
|
|
|
|
free (nn);
|
2017-01-03 02:48:55 +00:00
|
|
|
return res;
|
2014-09-24 15:41:50 +00:00
|
|
|
}
|
2016-10-26 21:16:31 +00:00
|
|
|
if (sb.st_mode & S_ISUID) {
|
2014-09-24 15:41:50 +00:00
|
|
|
u_rwx[2] = (sb.st_mode & S_IXUSR) ? 's' : 'S';
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
|
|
|
if (isdir) {
|
|
|
|
fch = 'd';
|
|
|
|
} else {
|
2014-05-22 09:25:58 +00:00
|
|
|
switch (ifmt) {
|
|
|
|
case S_IFCHR: fch = 'c'; break;
|
|
|
|
case S_IFBLK: fch = 'b'; break;
|
|
|
|
case S_IFLNK: fch = 'l'; break;
|
|
|
|
case S_IFIFO: fch = 'p'; break;
|
2015-02-05 06:10:30 +00:00
|
|
|
#ifdef S_IFSOCK
|
2014-05-22 09:25:58 +00:00
|
|
|
case S_IFSOCK: fch = 's'; break;
|
2015-02-05 06:10:30 +00:00
|
|
|
#endif
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
|
|
|
#else
|
2015-10-23 10:07:07 +00:00
|
|
|
u_rwx = strdup ("-");
|
2014-05-22 09:25:58 +00:00
|
|
|
fch = isdir? 'd': '-';
|
|
|
|
#endif
|
2018-07-11 13:51:35 +00:00
|
|
|
if (printfmt == 'q') {
|
|
|
|
res = r_str_appendf (res, "%s\n", nn);
|
2018-09-13 14:45:31 +00:00
|
|
|
} else if (printfmt == 'e') {
|
|
|
|
ut32 ifmt = sb.st_mode & S_IFMT;
|
|
|
|
const char *eDIR = "📁";
|
|
|
|
const char *eLNK = "📎";
|
|
|
|
const char *eIMG = "🌅";
|
|
|
|
const char *eUID = "🔼";
|
|
|
|
const char *eHID = "👀";
|
|
|
|
const char *eANY = " ";
|
|
|
|
// --
|
|
|
|
const char *icon = eANY;
|
|
|
|
if (isdir) {
|
|
|
|
icon = eDIR;
|
|
|
|
} else if (ifmt == S_IFLNK) {
|
|
|
|
icon = eLNK;
|
|
|
|
} else if (sb.st_mode & S_ISUID) {
|
|
|
|
icon = eUID;
|
|
|
|
} else if (r_str_casestr (nn, ".jpg") || r_str_casestr (nn, ".png") || r_str_casestr (nn, ".gif")) {
|
|
|
|
icon = eIMG;
|
|
|
|
} else if (*nn == '.') {
|
|
|
|
icon = eHID;
|
|
|
|
}
|
|
|
|
res = r_str_appendf (res, "%s %s\n", icon, nn);
|
2018-07-11 13:51:35 +00:00
|
|
|
} else if (printfmt == FMT_RAW) {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "%c%s%s%s 1 %4d:%-4d %-10d %s\n",
|
2016-10-26 21:16:31 +00:00
|
|
|
isdir?'d': fch,
|
|
|
|
u_rwx? u_rwx: "-",
|
|
|
|
r_str_rwx_i ((perm >> 3) & 7),
|
|
|
|
r_str_rwx_i (perm & 7),
|
2015-10-22 23:39:47 +00:00
|
|
|
uid, gid, sz, nn);
|
2014-11-10 03:14:57 +00:00
|
|
|
} else if (printfmt == FMT_JSON) {
|
2016-10-26 21:16:31 +00:00
|
|
|
if (nth > 0) {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_append (res, ",");
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_appendf (res, "{\"name\":\"%s\",\"size\":%d,\"uid\":%d,"
|
2014-11-10 03:14:57 +00:00
|
|
|
"\"gid\":%d,\"perm\":%d,\"isdir\":%s}",
|
2018-07-11 13:51:35 +00:00
|
|
|
name, sz, uid, gid, perm, isdir? "true": "false");
|
2014-11-10 03:14:57 +00:00
|
|
|
}
|
2014-05-26 22:09:17 +00:00
|
|
|
free (nn);
|
2015-02-20 02:18:36 +00:00
|
|
|
free (u_rwx);
|
2017-01-03 02:48:55 +00:00
|
|
|
return res;
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
|
|
|
|
2014-02-18 03:03:07 +00:00
|
|
|
// TODO: Move into r_util .. r_print maybe? r_cons dep is anoying
|
2017-01-03 02:48:55 +00:00
|
|
|
R_API char *r_syscmd_ls(const char *input) {
|
|
|
|
char *res = NULL;
|
2014-02-18 03:03:07 +00:00
|
|
|
const char *path = ".";
|
2015-04-17 14:43:10 +00:00
|
|
|
char *d = NULL;
|
|
|
|
char *p = NULL;
|
|
|
|
char *homepath = NULL;
|
2015-04-16 11:11:21 +00:00
|
|
|
char *pattern = NULL;
|
2014-11-10 03:14:57 +00:00
|
|
|
int printfmt = 0;
|
2014-02-18 03:03:07 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RList *files;
|
2014-05-22 09:25:58 +00:00
|
|
|
char *name;
|
2014-02-18 03:03:07 +00:00
|
|
|
char *dir;
|
2015-04-16 11:11:21 +00:00
|
|
|
int off;
|
2017-01-13 11:49:28 +00:00
|
|
|
if (!input) {
|
|
|
|
input = "";
|
|
|
|
path = ".";
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2018-07-11 13:51:35 +00:00
|
|
|
if (*input == 'q') {
|
|
|
|
printfmt = 'q';
|
|
|
|
input++;
|
|
|
|
}
|
2014-06-14 00:59:12 +00:00
|
|
|
if (r_sandbox_enable (0)) {
|
|
|
|
eprintf ("Sandbox forbids listing directories\n");
|
2017-01-03 02:48:55 +00:00
|
|
|
return NULL;
|
2014-06-14 00:59:12 +00:00
|
|
|
}
|
2017-01-13 11:49:28 +00:00
|
|
|
if (*input && input[0] == ' ') {
|
|
|
|
input++;
|
|
|
|
}
|
|
|
|
if (*input) {
|
2018-07-11 13:51:35 +00:00
|
|
|
if ((!strncmp (input, "-h", 2))) {
|
2018-09-13 14:45:31 +00:00
|
|
|
eprintf ("Usage: ls ([-e,-l,-j,-q]) ([path]) # long, json, quiet\n");
|
|
|
|
} else if ((!strncmp (input, "-e", 2))) {
|
|
|
|
printfmt = 'e';
|
|
|
|
path = r_str_trim_ro (path + 1);
|
2018-07-11 13:51:35 +00:00
|
|
|
} else if ((!strncmp (input, "-q", 2))) {
|
|
|
|
printfmt = 'q';
|
2018-09-13 14:45:31 +00:00
|
|
|
path = r_str_trim_ro (path + 1);
|
2018-07-11 13:51:35 +00:00
|
|
|
} else if ((!strncmp (input, "-l", 2)) || (!strncmp (input, "-j", 2))) {
|
2017-01-13 11:49:28 +00:00
|
|
|
// mode = 'l';
|
|
|
|
if (input[2]) {
|
|
|
|
printfmt = (input[2] == 'j') ? FMT_JSON : FMT_RAW;
|
2018-09-13 14:45:31 +00:00
|
|
|
path = r_str_trim_ro (input + 2);
|
2016-10-26 21:16:31 +00:00
|
|
|
if (!*path) {
|
|
|
|
path = ".";
|
|
|
|
}
|
2017-01-13 11:49:28 +00:00
|
|
|
} else {
|
|
|
|
printfmt = FMT_RAW;
|
2014-02-18 03:03:07 +00:00
|
|
|
}
|
2016-10-26 21:16:31 +00:00
|
|
|
} else {
|
2017-01-13 11:49:28 +00:00
|
|
|
path = input;
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2015-04-17 14:43:10 +00:00
|
|
|
}
|
2017-08-24 11:31:27 +00:00
|
|
|
if (!path || !*path) {
|
|
|
|
path = ".";
|
2018-07-13 12:51:34 +00:00
|
|
|
} else if (!strncmp (path, "~/", 2)) {
|
2016-10-26 21:16:31 +00:00
|
|
|
homepath = r_str_home (path + 2);
|
|
|
|
if (homepath) {
|
|
|
|
path = (const char *)homepath;
|
|
|
|
}
|
|
|
|
} else if (*path == '$') {
|
2018-07-11 13:51:35 +00:00
|
|
|
if (!strncmp (path + 1, "home", 4) || !strncmp (path + 1, "HOME", 4)) {
|
|
|
|
homepath = r_str_home ((strlen (path) > 5)? path + 6: NULL);
|
2016-10-26 21:16:31 +00:00
|
|
|
if (homepath) {
|
|
|
|
path = (const char *)homepath;
|
|
|
|
}
|
2015-04-17 14:43:10 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-26 21:16:31 +00:00
|
|
|
if (!r_file_is_directory (path)) {
|
2017-01-03 02:48:55 +00:00
|
|
|
p = strrchr (path, '/');
|
2018-07-11 13:51:35 +00:00
|
|
|
if (p) {
|
2015-04-16 11:11:21 +00:00
|
|
|
off = p - path;
|
2016-10-26 21:16:31 +00:00
|
|
|
d = (char *) calloc (1, off + 1);
|
2015-06-01 21:05:44 +00:00
|
|
|
if (!d) {
|
|
|
|
free (homepath);
|
2017-01-03 02:48:55 +00:00
|
|
|
return NULL;
|
2015-06-01 21:05:44 +00:00
|
|
|
}
|
2015-04-16 11:11:21 +00:00
|
|
|
memcpy (d, path, off);
|
|
|
|
path = (const char *)d;
|
2016-10-26 21:16:31 +00:00
|
|
|
pattern = strdup (p + 1);
|
2015-10-25 00:32:22 +00:00
|
|
|
} else {
|
2015-04-16 11:11:21 +00:00
|
|
|
pattern = strdup (path);
|
|
|
|
path = ".";
|
|
|
|
}
|
2016-10-26 21:16:31 +00:00
|
|
|
} else {
|
|
|
|
pattern = strdup ("*");
|
|
|
|
}
|
2014-05-22 09:25:58 +00:00
|
|
|
if (r_file_is_regular (path)) {
|
2017-01-03 02:48:55 +00:00
|
|
|
res = showfile (res, 0, path, path, printfmt);
|
2015-04-19 01:27:16 +00:00
|
|
|
free (homepath);
|
|
|
|
free (pattern);
|
|
|
|
free (d);
|
2017-01-03 02:48:55 +00:00
|
|
|
return res;
|
2014-05-22 09:25:58 +00:00
|
|
|
}
|
2014-02-18 03:03:07 +00:00
|
|
|
files = r_sys_dir (path);
|
|
|
|
|
2017-01-03 02:48:55 +00:00
|
|
|
if (path[strlen (path) - 1] == '/') {
|
2014-11-10 03:14:57 +00:00
|
|
|
dir = strdup (path);
|
2016-10-26 21:16:31 +00:00
|
|
|
} else {
|
2017-03-16 21:29:49 +00:00
|
|
|
dir = r_str_append (strdup (path), "/");
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2014-05-22 09:25:58 +00:00
|
|
|
int nth = 0;
|
2016-10-26 21:16:31 +00:00
|
|
|
if (printfmt == FMT_JSON) {
|
2017-01-03 02:48:55 +00:00
|
|
|
res = strdup ("[");
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2015-08-18 00:44:59 +00:00
|
|
|
needs_newline = 0;
|
2014-02-18 03:03:07 +00:00
|
|
|
r_list_foreach (files, iter, name) {
|
2017-03-16 21:29:49 +00:00
|
|
|
char *n = r_str_append (strdup (dir), name);
|
2016-10-26 21:16:31 +00:00
|
|
|
if (!n) {
|
|
|
|
break;
|
|
|
|
}
|
2015-08-18 00:44:59 +00:00
|
|
|
if (r_str_glob (name, pattern)) {
|
2016-10-26 21:16:31 +00:00
|
|
|
if (*n) {
|
2017-01-03 02:48:55 +00:00
|
|
|
res = showfile (res, nth, n, name, printfmt);
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2015-04-16 11:11:21 +00:00
|
|
|
nth++;
|
|
|
|
}
|
2014-02-18 03:03:07 +00:00
|
|
|
free (n);
|
|
|
|
}
|
2016-10-26 21:16:31 +00:00
|
|
|
if (printfmt == FMT_JSON) {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_append (res, "]");
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
|
|
|
if (needs_newline) {
|
2017-03-16 21:29:49 +00:00
|
|
|
res = r_str_append (res, "\n");
|
2016-10-26 21:16:31 +00:00
|
|
|
}
|
2014-02-18 03:03:07 +00:00
|
|
|
free (dir);
|
2015-04-24 09:05:42 +00:00
|
|
|
free (d);
|
|
|
|
free (homepath);
|
2015-04-16 11:11:21 +00:00
|
|
|
free (pattern);
|
2014-02-18 03:03:07 +00:00
|
|
|
r_list_free (files);
|
2017-01-03 02:48:55 +00:00
|
|
|
return res;
|
2014-02-18 03:03:07 +00:00
|
|
|
}
|
2014-08-06 22:37:44 +00:00
|
|
|
|
2017-01-03 02:48:55 +00:00
|
|
|
R_API char *r_syscmd_cat(const char *file) {
|
2014-09-20 12:43:18 +00:00
|
|
|
int sz;
|
2017-01-13 11:49:28 +00:00
|
|
|
const char *p = NULL;
|
|
|
|
if (file) {
|
|
|
|
if ((p = strchr (file, ' '))) {
|
|
|
|
p = p + 1;
|
|
|
|
} else {
|
|
|
|
p = file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p && *p) {
|
|
|
|
char *filename = strdup (p);
|
2018-01-08 02:22:26 +00:00
|
|
|
filename = r_str_trim (filename);
|
2017-01-13 11:49:28 +00:00
|
|
|
char *data = r_file_slurp (filename, &sz);
|
2017-01-03 16:58:36 +00:00
|
|
|
if (!data) {
|
2016-10-26 21:16:31 +00:00
|
|
|
eprintf ("No such file or directory\n");
|
|
|
|
}
|
2014-08-17 18:30:28 +00:00
|
|
|
free (filename);
|
2017-01-03 16:58:36 +00:00
|
|
|
return data;
|
2016-10-26 21:16:31 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Usage: cat [file]\n");
|
|
|
|
}
|
2017-01-03 02:48:55 +00:00
|
|
|
return NULL;
|
2014-08-06 22:37:44 +00:00
|
|
|
}
|
2015-04-02 13:30:21 +00:00
|
|
|
|
2017-01-03 02:48:55 +00:00
|
|
|
R_API char *r_syscmd_mkdir(const char *dir) {
|
2018-02-28 00:24:46 +00:00
|
|
|
const char *suffix = r_str_trim (strchr (dir, ' '));
|
|
|
|
if (!suffix || !strncmp (suffix, "-p", 3)) {
|
|
|
|
return r_str_dup (NULL, "Usage: mkdir [-p] [directory]\n");
|
2015-10-18 22:33:22 +00:00
|
|
|
}
|
2018-02-28 00:24:46 +00:00
|
|
|
int ret;
|
|
|
|
char *dirname;
|
|
|
|
if (!strncmp (suffix, "-p ", 3)) {
|
|
|
|
dirname = r_str_trim (strdup (suffix + 3));
|
|
|
|
ret = r_sys_mkdirp (dirname);
|
|
|
|
} else {
|
|
|
|
dirname = r_str_trim (strdup (suffix));
|
|
|
|
ret = r_sys_mkdir (dirname);
|
|
|
|
}
|
|
|
|
if (!ret) {
|
|
|
|
if (r_sys_mkdir_failed ()) {
|
2018-03-19 10:51:04 +00:00
|
|
|
char *res = r_str_newf ("Cannot create \"%s\"\n", dirname);
|
|
|
|
free (dirname);
|
|
|
|
return res;
|
2018-02-28 00:24:46 +00:00
|
|
|
}
|
2015-10-18 22:33:22 +00:00
|
|
|
}
|
2018-02-28 00:24:46 +00:00
|
|
|
free (dirname);
|
2017-01-03 02:48:55 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API bool r_syscmd_mv(const char *input) {
|
|
|
|
if (strlen (input) < 3) {
|
|
|
|
eprintf ("Usage: mv src dst\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
input = input + 2;
|
|
|
|
if (!r_sandbox_enable (0)) {
|
|
|
|
#if __WINDOWS__
|
|
|
|
r_sys_cmdf ("move %s", input);
|
|
|
|
#else
|
|
|
|
r_sys_cmdf ("mv %s", input);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return false;
|
2015-04-02 13:30:21 +00:00
|
|
|
}
|