mirror of https://github.com/ericonr/erm.git
Split implementation into two files.
- also fix threadings bugs: threads could leak (if the join loop exited due to some error) or non existent threads could be joined (we add the created struct member to avoid this)
This commit is contained in:
parent
75c36e6432
commit
e24aef5395
55
erm.c
55
erm.c
|
@ -1,7 +1,4 @@
|
|||
#define _XOPEN_SOURCE 500 /* nftw */
|
||||
#include <errno.h>
|
||||
#include <ftw.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdnoreturn.h>
|
||||
#include <stdio.h>
|
||||
|
@ -9,41 +6,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int ftw_cb(const char *fpath, const struct stat *sb,
|
||||
int typeflag, struct FTW *ftwbuf)
|
||||
{
|
||||
if (typeflag == FTW_D || typeflag == FTW_DP) return rmdir(fpath);
|
||||
else return unlink(fpath);
|
||||
}
|
||||
|
||||
struct task {
|
||||
pthread_t thread;
|
||||
const char *path;
|
||||
int rv;
|
||||
} *task_list = NULL;
|
||||
|
||||
void *run_ftw(void *arg)
|
||||
{
|
||||
struct task *t = arg;
|
||||
t->rv = nftw(t->path, ftw_cb, 20, FTW_DEPTH|FTW_PHYS);
|
||||
return NULL;
|
||||
}
|
||||
static int recurse_into(const char *path, int c)
|
||||
{
|
||||
task_list[c].path = path;
|
||||
return pthread_create(&task_list[c].thread, NULL, run_ftw, &task_list[c]);
|
||||
}
|
||||
static int join_thread(const char *path, int c)
|
||||
{
|
||||
pthread_join(task_list[c].thread, NULL);
|
||||
return task_list[c].rv;
|
||||
}
|
||||
|
||||
static int single_file(const char *path, int c)
|
||||
{
|
||||
(void)c;
|
||||
return remove(path);
|
||||
}
|
||||
#include "erm.h"
|
||||
|
||||
noreturn static void usage(int s)
|
||||
{
|
||||
|
@ -73,16 +36,18 @@ int main(int argc, char **argv)
|
|||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc == 0) {
|
||||
usage(1);
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
task_list = calloc(sizeof(*task_list), argc);
|
||||
if (!task_list) {
|
||||
if (!malloc_task_list(argc)) {
|
||||
perror("malloc");
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
int (*action)(const char *, int) = recursive ? recurse_into : single_file;
|
||||
int (*callback)(const char *, int) = recursive ? join_thread : NULL;
|
||||
file_action action = recursive ? recurse_into : single_file;
|
||||
file_action callback = recursive ? join_thread : NULL;
|
||||
const char *err_fmt = recursive ?
|
||||
"failed to delve into '%s': %s\n" : "failed to remove '%s': %s\n";
|
||||
|
||||
|
@ -103,11 +68,7 @@ int main(int argc, char **argv)
|
|||
const char *path = argv[i];
|
||||
if (callback(path, i)) {
|
||||
fprintf(stderr, err_fmt, path, strerror(errno));
|
||||
if (stop_at_error) {
|
||||
return 1;
|
||||
} else {
|
||||
rv = 1;
|
||||
}
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
typedef int (*file_action)(const char *path, int position);
|
||||
struct task;
|
||||
|
||||
/* remove.c */
|
||||
struct task *malloc_task_list(size_t);
|
||||
int recurse_into(const char *, int);
|
||||
int join_thread(const char *, int);
|
||||
int single_file(const char *, int);
|
|
@ -0,0 +1,60 @@
|
|||
#define _XOPEN_SOURCE 500 /* nftw */
|
||||
#include <errno.h>
|
||||
#include <ftw.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "erm.h"
|
||||
|
||||
struct task {
|
||||
pthread_t thread;
|
||||
const char *path;
|
||||
int rv;
|
||||
int created;
|
||||
} *task_list = NULL;
|
||||
|
||||
struct task *malloc_task_list(size_t n)
|
||||
{
|
||||
return task_list = calloc(sizeof(struct task), n);
|
||||
}
|
||||
|
||||
static int ftw_cb(const char *fpath, const struct stat *sb,
|
||||
int typeflag, struct FTW *ftwbuf)
|
||||
{
|
||||
if (typeflag == FTW_D || typeflag == FTW_DP) return rmdir(fpath);
|
||||
else return unlink(fpath);
|
||||
}
|
||||
static void *run_ftw(void *arg)
|
||||
{
|
||||
struct task *t = arg;
|
||||
t->rv = nftw(t->path, ftw_cb, 20, FTW_DEPTH|FTW_PHYS) ? errno : 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int recurse_into(const char *path, int c)
|
||||
{
|
||||
task_list[c].path = path;
|
||||
int rv = pthread_create(&task_list[c].thread, NULL, run_ftw, &task_list[c]);
|
||||
if (!rv) task_list[c].created = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int join_thread(const char *path, int c)
|
||||
{
|
||||
if (!task_list[c].created) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pthread_join(task_list[c].thread, NULL);
|
||||
errno = task_list[c].rv;
|
||||
return errno ? -1 : 0;
|
||||
}
|
||||
|
||||
int single_file(const char *path, int c)
|
||||
{
|
||||
(void)c;
|
||||
return remove(path);
|
||||
}
|
Loading…
Reference in New Issue