Refactor ls command for rzshell (#3600)
This commit is contained in:
parent
6452be6c20
commit
8135a450e9
5 changed files with 280 additions and 248 deletions
|
|
@ -3,6 +3,234 @@
|
|||
|
||||
#include <rz_core.h>
|
||||
|
||||
#define FMT_NONE 0
|
||||
#define FMT_RAW 1
|
||||
#define FMT_JSON 2
|
||||
|
||||
static char *showfile(char *res, const int nth, const char *fpath, const char *name, int printfmt) {
|
||||
static int needs_newline = 0;
|
||||
#if __UNIX__
|
||||
struct stat sb;
|
||||
#endif
|
||||
const char *n = fpath;
|
||||
char *nn, *u_rwx = NULL;
|
||||
int sz = rz_file_size(n);
|
||||
int perm, uid = 0, gid = 0;
|
||||
int fch = '-';
|
||||
if (!strncmp(fpath, "./", 2)) {
|
||||
fpath = fpath + 2;
|
||||
}
|
||||
const bool isdir = rz_file_is_directory(n);
|
||||
if (isdir) {
|
||||
nn = rz_str_append(strdup(fpath), "/");
|
||||
} else {
|
||||
nn = strdup(fpath);
|
||||
}
|
||||
if (!*nn) {
|
||||
free(nn);
|
||||
return res;
|
||||
}
|
||||
perm = isdir ? 0755 : 0644;
|
||||
if (!printfmt) {
|
||||
needs_newline = ((nth + 1) % 4) ? 1 : 0;
|
||||
res = rz_str_appendf(res, "%18s%s", nn, needs_newline ? " " : "\n");
|
||||
free(nn);
|
||||
return res;
|
||||
}
|
||||
// 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;
|
||||
if (!(u_rwx = strdup(rz_str_rwx_i(perm >> 6)))) {
|
||||
free(nn);
|
||||
return res;
|
||||
}
|
||||
if (sb.st_mode & S_ISUID) {
|
||||
u_rwx[2] = (sb.st_mode & S_IXUSR) ? 's' : 'S';
|
||||
}
|
||||
if (isdir) {
|
||||
fch = 'd';
|
||||
} else {
|
||||
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;
|
||||
#ifdef S_IFSOCK
|
||||
case S_IFSOCK: fch = 's'; break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
u_rwx = strdup("-");
|
||||
fch = isdir ? 'd' : '-';
|
||||
#endif
|
||||
if (printfmt == 'q') {
|
||||
res = rz_str_appendf(res, "%s\n", nn);
|
||||
} else if (printfmt == 'e') {
|
||||
const char *eDIR = "📁";
|
||||
const char *eIMG = "🌅";
|
||||
const char *eHID = "👀";
|
||||
const char *eANY = " ";
|
||||
// --
|
||||
const char *icon = eANY;
|
||||
if (isdir) {
|
||||
icon = eDIR;
|
||||
#if __UNIX__
|
||||
} else if ((sb.st_mode & S_IFMT) == S_IFLNK) {
|
||||
const char *eLNK = "📎";
|
||||
icon = eLNK;
|
||||
} else if (sb.st_mode & S_ISUID) {
|
||||
const char *eUID = "🔼";
|
||||
icon = eUID;
|
||||
#endif
|
||||
} else if (rz_str_casestr(nn, ".jpg") || rz_str_casestr(nn, ".png") || rz_str_casestr(nn, ".gif")) {
|
||||
icon = eIMG;
|
||||
} else if (*nn == '.') {
|
||||
icon = eHID;
|
||||
}
|
||||
res = rz_str_appendf(res, "%s %s\n", icon, nn);
|
||||
} else if (printfmt == FMT_RAW) {
|
||||
res = rz_str_appendf(res, "%c%s%s%s 1 %4d:%-4d %-10d %s\n",
|
||||
isdir ? 'd' : fch,
|
||||
u_rwx ? u_rwx : "-",
|
||||
rz_str_rwx_i((perm >> 3) & 7),
|
||||
rz_str_rwx_i(perm & 7),
|
||||
uid, gid, sz, nn);
|
||||
} else if (printfmt == FMT_JSON) {
|
||||
if (nth > 0) {
|
||||
res = rz_str_append(res, ",");
|
||||
}
|
||||
res = rz_str_appendf(res, "{\"name\":\"%s\",\"size\":%d,\"uid\":%d,"
|
||||
"\"gid\":%d,\"perm\":%d,\"isdir\":%s}",
|
||||
name, sz, uid, gid, perm, isdir ? "true" : "false");
|
||||
}
|
||||
free(nn);
|
||||
free(u_rwx);
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *syscmd_ls(RZ_NONNULL const int argc, const char **argv) {
|
||||
static int needs_newline = 0;
|
||||
char *res = NULL;
|
||||
const char *path = ".";
|
||||
char *d = NULL;
|
||||
char *p = NULL;
|
||||
char *homepath = NULL;
|
||||
char *pattern = NULL;
|
||||
int printfmt = 0;
|
||||
RzListIter *iter;
|
||||
RzList *files;
|
||||
char *name;
|
||||
char *dir;
|
||||
int off;
|
||||
int path_in_second_arg = 0;
|
||||
if (argc > 1) {
|
||||
if ((!strncmp(argv[1], "-h", 2))) {
|
||||
eprintf("Usage: ls ([-e,-l,-j,-q]) ([path]) # long, json, quiet\n");
|
||||
return NULL;
|
||||
} else if ((!strncmp(argv[1], "-e", 2))) {
|
||||
printfmt = 'e';
|
||||
} else if ((!strncmp(argv[1], "-q", 2))) {
|
||||
printfmt = 'q';
|
||||
} else if ((!strncmp(argv[1], "-l", 2)) || (!strncmp(argv[1], "-j", 2))) {
|
||||
printfmt = (argv[1][1] == 'j') ? FMT_JSON : FMT_RAW;
|
||||
} else {
|
||||
path = argv[1];
|
||||
path_in_second_arg = 1;
|
||||
}
|
||||
if (argc >= 3) {
|
||||
if (!path_in_second_arg) {
|
||||
path = argv[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (RZ_STR_ISEMPTY(path)) {
|
||||
path = ".";
|
||||
} else if (rz_str_startswith(path, "~")) {
|
||||
homepath = rz_path_home_expand(path);
|
||||
if (homepath) {
|
||||
path = (const char *)homepath;
|
||||
}
|
||||
} else if (*path == '$') {
|
||||
if (!strncmp(path + 1, "home", 4) || !strncmp(path + 1, "HOME", 4)) {
|
||||
homepath = rz_str_home((strlen(path) > 5) ? path + 6 : NULL);
|
||||
if (homepath) {
|
||||
path = (const char *)homepath;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rz_file_is_directory(path)) {
|
||||
p = strrchr(path, '/');
|
||||
if (p) {
|
||||
off = p - path;
|
||||
d = (char *)calloc(1, off + 1);
|
||||
if (!d) {
|
||||
free(homepath);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(d, path, off);
|
||||
path = (const char *)d;
|
||||
pattern = strdup(p + 1);
|
||||
} else {
|
||||
pattern = strdup(path);
|
||||
path = ".";
|
||||
}
|
||||
} else {
|
||||
pattern = strdup("*");
|
||||
}
|
||||
if (rz_file_is_regular(path)) {
|
||||
res = showfile(res, 0, path, path, printfmt);
|
||||
free(homepath);
|
||||
free(pattern);
|
||||
free(d);
|
||||
return res;
|
||||
}
|
||||
files = rz_sys_dir(path);
|
||||
|
||||
if (path[strlen(path) - 1] == '/') {
|
||||
dir = strdup(path);
|
||||
} else {
|
||||
dir = rz_str_append(strdup(path), "/");
|
||||
}
|
||||
int nth = 0;
|
||||
if (printfmt == FMT_JSON) {
|
||||
res = strdup("[");
|
||||
}
|
||||
needs_newline = 0;
|
||||
rz_list_foreach (files, iter, name) {
|
||||
char *n = rz_str_append(strdup(dir), name);
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
if (rz_str_glob(name, pattern)) {
|
||||
if (*n) {
|
||||
res = showfile(res, nth, n, name, printfmt);
|
||||
}
|
||||
nth++;
|
||||
}
|
||||
free(n);
|
||||
}
|
||||
if (printfmt == FMT_JSON) {
|
||||
res = rz_str_append(res, "]");
|
||||
}
|
||||
if (needs_newline) {
|
||||
res = rz_str_append(res, "\n");
|
||||
}
|
||||
free(dir);
|
||||
free(d);
|
||||
free(homepath);
|
||||
free(pattern);
|
||||
rz_list_free(files);
|
||||
return res;
|
||||
}
|
||||
|
||||
static const char *findBreakChar(const char *s) {
|
||||
while (*s) {
|
||||
if (!rz_name_validate_char(*s, true)) {
|
||||
|
|
@ -111,9 +339,7 @@ RZ_IPI RzCmdStatus rz_cmd_shell_exit_handler(RzCore *core, int argc, const char
|
|||
|
||||
// ls
|
||||
RZ_IPI RzCmdStatus rz_cmd_shell_ls_handler(RzCore *core, int argc, const char **argv) {
|
||||
char *arg = rz_str_array_join(argv + 1, argc - 1, " ");
|
||||
char *res = rz_syscmd_ls(arg);
|
||||
free(arg);
|
||||
char *res = syscmd_ls(argc, argv);
|
||||
if (!res) {
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -806,7 +806,7 @@ static const RzCmdDescArg yank_paste_args[2];
|
|||
static const RzCmdDescArg yank_string_args[2];
|
||||
static const RzCmdDescArg cmd_shell_diff_args[3];
|
||||
static const RzCmdDescArg cmd_shell_env_args[3];
|
||||
static const RzCmdDescArg cmd_shell_ls_args[2];
|
||||
static const RzCmdDescArg cmd_shell_ls_args[6];
|
||||
static const RzCmdDescArg cmd_shell_rm_args[2];
|
||||
static const RzCmdDescArg cmd_shell_sleep_args[2];
|
||||
static const RzCmdDescArg cmd_shell_uniq_args[2];
|
||||
|
|
@ -18003,9 +18003,36 @@ static const RzCmdDescHelp cmd_shell_exit_help = {
|
|||
|
||||
static const RzCmdDescArg cmd_shell_ls_args[] = {
|
||||
{
|
||||
.name = "arg",
|
||||
.type = RZ_CMD_ARG_TYPE_STRING,
|
||||
.flags = RZ_CMD_ARG_FLAG_ARRAY,
|
||||
.name = "e",
|
||||
.type = RZ_CMD_ARG_TYPE_OPTION,
|
||||
.flags = RZ_CMD_ARG_FLAG_OPTION,
|
||||
.optional = true,
|
||||
|
||||
},
|
||||
{
|
||||
.name = "q",
|
||||
.type = RZ_CMD_ARG_TYPE_OPTION,
|
||||
.flags = RZ_CMD_ARG_FLAG_OPTION,
|
||||
.optional = true,
|
||||
|
||||
},
|
||||
{
|
||||
.name = "l",
|
||||
.type = RZ_CMD_ARG_TYPE_OPTION,
|
||||
.flags = RZ_CMD_ARG_FLAG_OPTION,
|
||||
.optional = true,
|
||||
|
||||
},
|
||||
{
|
||||
.name = "j",
|
||||
.type = RZ_CMD_ARG_TYPE_OPTION,
|
||||
.flags = RZ_CMD_ARG_FLAG_OPTION,
|
||||
.optional = true,
|
||||
|
||||
},
|
||||
{
|
||||
.name = "path",
|
||||
.type = RZ_CMD_ARG_TYPE_FILE,
|
||||
.optional = true,
|
||||
|
||||
},
|
||||
|
|
@ -18013,6 +18040,7 @@ static const RzCmdDescArg cmd_shell_ls_args[] = {
|
|||
};
|
||||
static const RzCmdDescHelp cmd_shell_ls_help = {
|
||||
.summary = "List files and directories",
|
||||
.args_str = " [-e -q -l -j] <dir/file>",
|
||||
.args = cmd_shell_ls_args,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -78,10 +78,26 @@ commands:
|
|||
- name: ls
|
||||
cname: cmd_shell_ls
|
||||
summary: List files and directories
|
||||
args_str: " [-e -q -l -j] <dir/file>"
|
||||
args:
|
||||
- name: arg
|
||||
type: RZ_CMD_ARG_TYPE_STRING
|
||||
flags: RZ_CMD_ARG_FLAG_ARRAY
|
||||
- name: e
|
||||
type: RZ_CMD_ARG_TYPE_OPTION
|
||||
flags: RZ_CMD_ARG_FLAG_OPTION
|
||||
optional: true
|
||||
- name: q
|
||||
type: RZ_CMD_ARG_TYPE_OPTION
|
||||
flags: RZ_CMD_ARG_FLAG_OPTION
|
||||
optional: true
|
||||
- name: l
|
||||
type: RZ_CMD_ARG_TYPE_OPTION
|
||||
flags: RZ_CMD_ARG_FLAG_OPTION
|
||||
optional: true
|
||||
- name: j
|
||||
type: RZ_CMD_ARG_TYPE_OPTION
|
||||
flags: RZ_CMD_ARG_FLAG_OPTION
|
||||
optional: true
|
||||
- name: path
|
||||
type: RZ_CMD_ARG_TYPE_FILE
|
||||
optional: true
|
||||
- name: rm
|
||||
cname: cmd_shell_rm
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ RZ_API void rz_sys_backtrace(void);
|
|||
#endif
|
||||
|
||||
/* syscmd */
|
||||
RZ_API RZ_OWN char *rz_syscmd_ls(RZ_NONNULL const char *input);
|
||||
RZ_API RZ_OWN char *rz_syscmd_cat(RZ_NONNULL const char *file);
|
||||
RZ_API RZ_OWN char *rz_syscmd_mkdir(RZ_NONNULL const char *dir);
|
||||
RZ_API RZ_OWN char *rz_syscmd_uniq(RZ_NONNULL const char *file);
|
||||
|
|
|
|||
|
|
@ -4,243 +4,6 @@
|
|||
#include <rz_core.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define FMT_NONE 0
|
||||
#define FMT_RAW 1
|
||||
#define FMT_JSON 2
|
||||
|
||||
static int needs_newline = 0;
|
||||
|
||||
static char *showfile(char *res, const int nth, const char *fpath, const char *name, int printfmt) {
|
||||
#if __UNIX__
|
||||
struct stat sb;
|
||||
#endif
|
||||
const char *n = fpath;
|
||||
char *nn, *u_rwx = NULL;
|
||||
int sz = rz_file_size(n);
|
||||
int perm, uid = 0, gid = 0;
|
||||
int fch = '-';
|
||||
if (!strncmp(fpath, "./", 2)) {
|
||||
fpath = fpath + 2;
|
||||
}
|
||||
const bool isdir = rz_file_is_directory(n);
|
||||
if (isdir) {
|
||||
nn = rz_str_append(strdup(fpath), "/");
|
||||
} else {
|
||||
nn = strdup(fpath);
|
||||
}
|
||||
if (!*nn) {
|
||||
free(nn);
|
||||
return res;
|
||||
}
|
||||
perm = isdir ? 0755 : 0644;
|
||||
if (!printfmt) {
|
||||
needs_newline = ((nth + 1) % 4) ? 1 : 0;
|
||||
res = rz_str_appendf(res, "%18s%s", nn, needs_newline ? " " : "\n");
|
||||
free(nn);
|
||||
return res;
|
||||
}
|
||||
// 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;
|
||||
if (!(u_rwx = strdup(rz_str_rwx_i(perm >> 6)))) {
|
||||
free(nn);
|
||||
return res;
|
||||
}
|
||||
if (sb.st_mode & S_ISUID) {
|
||||
u_rwx[2] = (sb.st_mode & S_IXUSR) ? 's' : 'S';
|
||||
}
|
||||
if (isdir) {
|
||||
fch = 'd';
|
||||
} else {
|
||||
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;
|
||||
#ifdef S_IFSOCK
|
||||
case S_IFSOCK: fch = 's'; break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
u_rwx = strdup("-");
|
||||
fch = isdir ? 'd' : '-';
|
||||
#endif
|
||||
if (printfmt == 'q') {
|
||||
res = rz_str_appendf(res, "%s\n", nn);
|
||||
} else if (printfmt == 'e') {
|
||||
const char *eDIR = "📁";
|
||||
const char *eIMG = "🌅";
|
||||
const char *eHID = "👀";
|
||||
const char *eANY = " ";
|
||||
// --
|
||||
const char *icon = eANY;
|
||||
if (isdir) {
|
||||
icon = eDIR;
|
||||
#if __UNIX__
|
||||
} else if ((sb.st_mode & S_IFMT) == S_IFLNK) {
|
||||
const char *eLNK = "📎";
|
||||
icon = eLNK;
|
||||
} else if (sb.st_mode & S_ISUID) {
|
||||
const char *eUID = "🔼";
|
||||
icon = eUID;
|
||||
#endif
|
||||
} else if (rz_str_casestr(nn, ".jpg") || rz_str_casestr(nn, ".png") || rz_str_casestr(nn, ".gif")) {
|
||||
icon = eIMG;
|
||||
} else if (*nn == '.') {
|
||||
icon = eHID;
|
||||
}
|
||||
res = rz_str_appendf(res, "%s %s\n", icon, nn);
|
||||
} else if (printfmt == FMT_RAW) {
|
||||
res = rz_str_appendf(res, "%c%s%s%s 1 %4d:%-4d %-10d %s\n",
|
||||
isdir ? 'd' : fch,
|
||||
u_rwx ? u_rwx : "-",
|
||||
rz_str_rwx_i((perm >> 3) & 7),
|
||||
rz_str_rwx_i(perm & 7),
|
||||
uid, gid, sz, nn);
|
||||
} else if (printfmt == FMT_JSON) {
|
||||
if (nth > 0) {
|
||||
res = rz_str_append(res, ",");
|
||||
}
|
||||
res = rz_str_appendf(res, "{\"name\":\"%s\",\"size\":%d,\"uid\":%d,"
|
||||
"\"gid\":%d,\"perm\":%d,\"isdir\":%s}",
|
||||
name, sz, uid, gid, perm, isdir ? "true" : "false");
|
||||
}
|
||||
free(nn);
|
||||
free(u_rwx);
|
||||
return res;
|
||||
}
|
||||
|
||||
RZ_API RZ_OWN char *rz_syscmd_ls(RZ_NONNULL const char *input) {
|
||||
char *res = NULL;
|
||||
const char *path = ".";
|
||||
char *d = NULL;
|
||||
char *p = NULL;
|
||||
char *homepath = NULL;
|
||||
char *pattern = NULL;
|
||||
int printfmt = 0;
|
||||
RzListIter *iter;
|
||||
RzList *files;
|
||||
char *name;
|
||||
char *dir;
|
||||
int off;
|
||||
if (!input) {
|
||||
input = "";
|
||||
path = ".";
|
||||
}
|
||||
if (*input == 'q') {
|
||||
printfmt = 'q';
|
||||
input++;
|
||||
}
|
||||
if (*input && input[0] == ' ') {
|
||||
input++;
|
||||
}
|
||||
if (*input) {
|
||||
if ((!strncmp(input, "-h", 2))) {
|
||||
eprintf("Usage: ls ([-e,-l,-j,-q]) ([path]) # long, json, quiet\n");
|
||||
} else if ((!strncmp(input, "-e", 2))) {
|
||||
printfmt = 'e';
|
||||
path = rz_str_trim_head_ro(input + 2);
|
||||
} else if ((!strncmp(input, "-q", 2))) {
|
||||
printfmt = 'q';
|
||||
path = rz_str_trim_head_ro(input + 2);
|
||||
} else if ((!strncmp(input, "-l", 2)) || (!strncmp(input, "-j", 2))) {
|
||||
printfmt = (input[1] == 'j') ? FMT_JSON : FMT_RAW;
|
||||
path = rz_str_trim_head_ro(input + 2);
|
||||
if (!*path) {
|
||||
path = ".";
|
||||
}
|
||||
} else {
|
||||
path = input;
|
||||
}
|
||||
}
|
||||
if (!path || !*path) {
|
||||
path = ".";
|
||||
} else if (rz_str_startswith(path, "~")) {
|
||||
homepath = rz_path_home_expand(path);
|
||||
if (homepath) {
|
||||
path = (const char *)homepath;
|
||||
}
|
||||
} else if (*path == '$') {
|
||||
if (!strncmp(path + 1, "home", 4) || !strncmp(path + 1, "HOME", 4)) {
|
||||
homepath = rz_str_home((strlen(path) > 5) ? path + 6 : NULL);
|
||||
if (homepath) {
|
||||
path = (const char *)homepath;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rz_file_is_directory(path)) {
|
||||
p = strrchr(path, '/');
|
||||
if (p) {
|
||||
off = p - path;
|
||||
d = (char *)calloc(1, off + 1);
|
||||
if (!d) {
|
||||
free(homepath);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(d, path, off);
|
||||
path = (const char *)d;
|
||||
pattern = strdup(p + 1);
|
||||
} else {
|
||||
pattern = strdup(path);
|
||||
path = ".";
|
||||
}
|
||||
} else {
|
||||
pattern = strdup("*");
|
||||
}
|
||||
if (rz_file_is_regular(path)) {
|
||||
res = showfile(res, 0, path, path, printfmt);
|
||||
free(homepath);
|
||||
free(pattern);
|
||||
free(d);
|
||||
return res;
|
||||
}
|
||||
files = rz_sys_dir(path);
|
||||
|
||||
if (path[strlen(path) - 1] == '/') {
|
||||
dir = strdup(path);
|
||||
} else {
|
||||
dir = rz_str_append(strdup(path), "/");
|
||||
}
|
||||
int nth = 0;
|
||||
if (printfmt == FMT_JSON) {
|
||||
res = strdup("[");
|
||||
}
|
||||
needs_newline = 0;
|
||||
rz_list_foreach (files, iter, name) {
|
||||
char *n = rz_str_append(strdup(dir), name);
|
||||
if (!n) {
|
||||
break;
|
||||
}
|
||||
if (rz_str_glob(name, pattern)) {
|
||||
if (*n) {
|
||||
res = showfile(res, nth, n, name, printfmt);
|
||||
}
|
||||
nth++;
|
||||
}
|
||||
free(n);
|
||||
}
|
||||
if (printfmt == FMT_JSON) {
|
||||
res = rz_str_append(res, "]");
|
||||
}
|
||||
if (needs_newline) {
|
||||
res = rz_str_append(res, "\n");
|
||||
}
|
||||
free(dir);
|
||||
free(d);
|
||||
free(homepath);
|
||||
free(pattern);
|
||||
rz_list_free(files);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cmpstr(const void *_a, const void *_b) {
|
||||
const char *a = _a, *b = _b;
|
||||
return (int)strcmp(a, b);
|
||||
|
|
|
|||
Loading…
Reference in a new issue