~sircmpwn/ctools

d3db9d42f49868a1067cba1780a6004c66f2503c — dax 1 year, 2 months ago 11e35c0
Implement rmdir
8 files changed, 96 insertions(+), 1 deletions(-)

M STATUS
M doc/ctools.7.scd
M doc/meson.build
A doc/rmdir.1.scd
M meson.build
A src/rmdir.c
M test/meson.build
A test/rmdir
M STATUS => STATUS +1 -1
@@ 117,7 117,7 @@ T       pwd
T       renice
T       rm
    W   rmdel
T       rmdir
  D     rmdir
    W   sact
    W   sccs
T       sed

M doc/ctools.7.scd => doc/ctools.7.scd +2 -0
@@ 45,6 45,8 @@ shell environment. These tools are used for tasks such as:
:  Print the name of the login user
|  *nice*(1)
:  Run a process with an altered niceness value
|  *rmdir*(1)
:  Remove directories
|  *true*(1)
:  Exit with status code 0
|  *tty*(1)

M doc/meson.build => doc/meson.build +1 -0
@@ 17,6 17,7 @@ man_files = [
	'link.1',
	'logname.1',
	'nice.1',
	'rmdir.1',
	'true.1',
	'tty.1',
	'uname.1',

A doc/rmdir.1.scd => doc/rmdir.1.scd +26 -0
@@ 0,0 1,26 @@
rmdir(1) "ctools"

# NAME

rmdir - remove directories

# SYNOPSYS

*rmdir* [-p] _dir_...

# DESCRIPTION

*rmdir* will remove empty directories.

# OPTIONS

*-p*
	Remove a directory and all of its ancestors. For example, rmdir a/b/c
	will remove a/b/c, then a/b, and finally a.

# DISCLAIMER

This command is part of ctools and is compatible with POSIX-1.2017, and may
optionally support XSI extensions. This man page is not intended to be a
complete reference, and where it disagrees with the specification, the
specification takes precedence.

M meson.build => meson.build +1 -0
@@ 23,6 23,7 @@ oneshots = [
	'head',
	'logname',
	'nice', # Included in base but only effective under XSI
	'rmdir',
	'true',
	'tty',
	'uname',

A src/rmdir.c => src/rmdir.c +46 -0
@@ 0,0 1,46 @@
#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static void
usage(void)
{
	fprintf(stderr, "usage: rmdir [-p] dir...\n");
}

int
main(int argc, char *argv[])
{
	bool remove_path = false;
	char opt;
	while ((opt = getopt(argc, argv, "p")) != -1) {
		switch (opt) {
		case 'p':
			remove_path = true;
			break;
		default:
			usage();
			return 1;
		}
	}

	if (argc == optind) {
		usage();
		return 1;
	}

	for (int i = optind; i < argc; i++) {
		char *path = argv[i];
		do {
			if (rmdir(path) < 0) {
				perror("rmdir");
				return 1;
			}
		} while (remove_path && strcmp(dirname(path), ".") != 0);
	}

	return 0;
}


M test/meson.build => test/meson.build +1 -0
@@ 13,6 13,7 @@ test_files = [
	'head',
	'logname',
	'nice',
	'rmdir',
	'true',
	'tty',
	'uname',

A test/rmdir => test/rmdir +18 -0
@@ 0,0 1,18 @@
#!/bin/sh
. "$HARNESS" link

should_remove_dirs() {
	mkdir foo bar
	rmdir foo bar
	[ ! -d foo ] && [ ! -d bar ]
}

should_remove_paths() {
	mkdir -p foo/bar bar/baz
	rmdir -p foo/bar bar/baz
	[ ! -d foo ] && [ ! -d bar ]
}

runtests \
	should_remove_dirs
	should_remove_paths