Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/sort/sort.c
Show All 24 Lines | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/capsicum.h> | |||||
#include <sys/nv.h> | |||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <capsicum_helpers.h> | |||||
#include <casper/cap_exec.h> | |||||
#include <casper/cap_fileargs.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <getopt.h> | #include <getopt.h> | ||||
#include <libcasper.h> | |||||
#include <libgen.h> | |||||
#include <limits.h> | #include <limits.h> | ||||
#include <locale.h> | #include <locale.h> | ||||
#include <md5.h> | #include <md5.h> | ||||
#include <regex.h> | #include <regex.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
static bool print_symbols_on_debug; | static bool print_symbols_on_debug; | ||||
/* | /* | ||||
* Arguments from file (when file0-from option is used: | * Arguments from file (when file0-from option is used: | ||||
*/ | */ | ||||
static size_t argc_from_file0 = (size_t)-1; | static size_t argc_from_file0 = (size_t)-1; | ||||
static char **argv_from_file0; | static char **argv_from_file0; | ||||
fileargs_t *fa_in; | |||||
fileargs_t *fa_out; | |||||
cap_exec_t *capexec; | |||||
/* | /* | ||||
* Placeholder symbols for options which have no single-character equivalent | * Placeholder symbols for options which have no single-character equivalent | ||||
*/ | */ | ||||
enum | enum | ||||
{ | { | ||||
SORT_OPT = CHAR_MAX + 1, | SORT_OPT = CHAR_MAX + 1, | ||||
HELP_OPT, | HELP_OPT, | ||||
FF_OPT, | FF_OPT, | ||||
▲ Show 20 Lines • Show All 848 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Main function. | * Main function. | ||||
*/ | */ | ||||
int | int | ||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||
{ | { | ||||
char *argv_out[2]; | |||||
cap_rights_t rights; | |||||
cap_channel_t *capcas; | |||||
char *outfile, *real_outfile; | char *outfile, *real_outfile; | ||||
char *random_source = NULL; | char *random_source = NULL; | ||||
int c, result; | int argc_out, c, outdir, result; | ||||
bool mef_flags[NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS] = | bool mef_flags[NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS] = | ||||
{ false, false, false, false, false, false }; | { false, false, false, false, false, false }; | ||||
result = 0; | result = 0; | ||||
outfile = sort_strdup("-"); | outfile = sort_strdup("-"); | ||||
real_outfile = NULL; | real_outfile = NULL; | ||||
struct sort_mods *sm = &default_sort_mods_object; | struct sort_mods *sm = &default_sort_mods_object; | ||||
▲ Show 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | #endif | ||||
argc -= optind; | argc -= optind; | ||||
argv += optind; | argv += optind; | ||||
if (argv_from_file0) { | if (argv_from_file0) { | ||||
argc = argc_from_file0; | argc = argc_from_file0; | ||||
argv = argv_from_file0; | argv = argv_from_file0; | ||||
} | } | ||||
/* Case when the outfile equals one of the input files: */ | |||||
if (strcmp(outfile, "-")) { | |||||
for(int i = 0; i < argc; ++i) { | |||||
if (strcmp(argv[i], outfile) == 0) { | |||||
real_outfile = sort_strdup(outfile); | |||||
for(;;) { | |||||
char* tmp = sort_malloc(strlen(outfile) + | |||||
strlen(".tmp") + 1); | |||||
strcpy(tmp, outfile); | |||||
strcpy(tmp + strlen(tmp), ".tmp"); | |||||
sort_free(outfile); | |||||
outfile = tmp; | |||||
if (access(outfile, F_OK) < 0) | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
argc_out = 1; | |||||
argv_out[0] = outfile; | |||||
yzhong_freebsdfoundation.org: If outputting to stdout, outfile will be '-', in which case it would make no sense to add it to… | |||||
if (real_outfile) { | |||||
++argc_out; | |||||
argv_out[1] = real_outfile; | |||||
/* Open the output directory now, as we will later rename/delete files there */ | |||||
char* tmp = sort_malloc(strlen(real_outfile) + 1); | |||||
strcpy(tmp, real_outfile); | |||||
if ((outdir = open(dirname(tmp), O_DIRECTORY)) < 0) | |||||
err(1, NULL); | |||||
sort_free(tmp); | |||||
cap_rights_init(&rights, CAP_RENAMEAT_SOURCE, CAP_RENAMEAT_TARGET, CAP_UNLINKAT); | |||||
caph_rights_limit(outdir, &rights); | |||||
} | |||||
/* Open the temporary files directory */ | |||||
if ((tmpdir_fd = open(tmpdir, O_DIRECTORY)) == -1) | |||||
err(1, NULL); | |||||
cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, CAP_LOOKUP, | |||||
CAP_PWRITE, CAP_READ, CAP_UNLINKAT, CAP_FSTAT); | |||||
caph_rights_limit(tmpdir_fd, &rights); | |||||
capcas = cap_init(); | |||||
/* Initialize input and output fileargs */ | |||||
cap_rights_init(&rights, CAP_FCNTL, CAP_READ, CAP_FSTAT); | |||||
fa_in = fileargs_cinit(capcas, argc, argv, O_RDONLY, 0, &rights, FA_OPEN); | |||||
cap_rights_init(&rights, CAP_FCNTL, CAP_WRITE, CAP_FSTAT); | |||||
fa_out = fileargs_cinit(capcas, argc_out, argv_out, O_WRONLY | O_CREAT | O_TRUNC, | |||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &rights, FA_OPEN); | |||||
if (fa_in == NULL || fa_out == NULL) | |||||
err(1, "unable to set limits"); | |||||
/* Open cap_exec service, if needed */ | |||||
if (compress_program != NULL) { | |||||
capexec = cap_exec_init(capcas, 1, &compress_program); | |||||
} | |||||
cap_close(capcas); | |||||
caph_limit_stdio(); | |||||
#ifndef WITHOUT_NLS | #ifndef WITHOUT_NLS | ||||
catalog = catopen("sort", NL_CAT_LOCALE); | catalog = catopen("sort", NL_CAT_LOCALE); | ||||
#endif | #endif | ||||
if (sort_opts_vals.cflag && sort_opts_vals.mflag) | if (sort_opts_vals.cflag && sort_opts_vals.mflag) | ||||
errx(1, "%c:%c: %s", 'm', 'c', getstr(1)); | errx(1, "%c:%c: %s", 'm', 'c', getstr(1)); | ||||
#ifndef WITHOUT_NLS | #ifndef WITHOUT_NLS | ||||
catclose(catalog); | catclose(catalog); | ||||
#endif | #endif | ||||
if (caph_enter_casper() < 0) | |||||
err(1, "cap_enter"); | |||||
if (keys_num == 0) { | if (keys_num == 0) { | ||||
keys_num = 1; | keys_num = 1; | ||||
keys = sort_realloc(keys, sizeof(struct key_specs)); | keys = sort_realloc(keys, sizeof(struct key_specs)); | ||||
memset(&(keys[0]), 0, sizeof(struct key_specs)); | memset(&(keys[0]), 0, sizeof(struct key_specs)); | ||||
keys[0].c1 = 1; | keys[0].c1 = 1; | ||||
keys[0].pos1b = default_sort_mods->bflag; | keys[0].pos1b = default_sort_mods->bflag; | ||||
keys[0].pos2b = default_sort_mods->bflag; | keys[0].pos2b = default_sort_mods->bflag; | ||||
memcpy(&(keys[0].sm), default_sort_mods, | memcpy(&(keys[0].sm), default_sort_mods, | ||||
Show All 33 Lines | if (print_symbols_on_debug) { | ||||
printf("Positive sign: <%lc>\n", symbol_positive_sign); | printf("Positive sign: <%lc>\n", symbol_positive_sign); | ||||
printf("Negative sign: <%lc>\n", symbol_negative_sign); | printf("Negative sign: <%lc>\n", symbol_negative_sign); | ||||
} | } | ||||
} | } | ||||
if (need_random) | if (need_random) | ||||
get_random_seed(random_source); | get_random_seed(random_source); | ||||
/* Case when the outfile equals one of the input files: */ | |||||
if (strcmp(outfile, "-")) { | |||||
for(int i = 0; i < argc; ++i) { | |||||
if (strcmp(argv[i], outfile) == 0) { | |||||
real_outfile = sort_strdup(outfile); | |||||
for(;;) { | |||||
char* tmp = sort_malloc(strlen(outfile) + | |||||
strlen(".tmp") + 1); | |||||
strcpy(tmp, outfile); | |||||
strcpy(tmp + strlen(tmp), ".tmp"); | |||||
sort_free(outfile); | |||||
outfile = tmp; | |||||
if (access(outfile, F_OK) < 0) | |||||
break; | |||||
} | |||||
tmp_file_atexit(outfile); | |||||
} | |||||
} | |||||
} | |||||
#if defined(SORT_THREADS) | #if defined(SORT_THREADS) | ||||
if ((argc < 1) || (strcmp(outfile, "-") == 0) || (*outfile == 0)) | if ((argc < 1) || (strcmp(outfile, "-") == 0) || (*outfile == 0)) | ||||
nthreads = 1; | nthreads = 1; | ||||
#endif | #endif | ||||
if (!sort_opts_vals.cflag && !sort_opts_vals.mflag) { | if (!sort_opts_vals.cflag && !sort_opts_vals.mflag) { | ||||
struct file_list fl; | struct file_list fl; | ||||
struct sort_list list; | struct sort_list list; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (argc == 0) | ||||
file_list_add(&fl, "-", true); | file_list_add(&fl, "-", true); | ||||
else | else | ||||
file_list_populate(&fl, argc, argv, true); | file_list_populate(&fl, argc, argv, true); | ||||
merge_files(&fl, outfile); | merge_files(&fl, outfile); | ||||
file_list_clean(&fl); | file_list_clean(&fl); | ||||
} | } | ||||
if (real_outfile) { | if (real_outfile) { | ||||
unlink(real_outfile); | unlinkat(outdir, real_outfile, 0); | ||||
if (rename(outfile, real_outfile) < 0) | if (renameat(outdir, outfile, outdir, real_outfile) < 0) | ||||
err(2, NULL); | err(2, NULL); | ||||
sort_free(real_outfile); | sort_free(real_outfile); | ||||
} | } | ||||
sort_free(outfile); | sort_free(outfile); | ||||
fileargs_free(fa_in); | |||||
fileargs_free(fa_out); | |||||
cap_exec_free(capexec); | |||||
return (result); | return (result); | ||||
} | } |
If outputting to stdout, outfile will be '-', in which case it would make no sense to add it to fileargs.