diff options
author | archcrack <johndoe.arch@outlook.com> | 2021-01-27 22:34:16 -0300 |
---|---|---|
committer | archcrack <johndoe.arch@outlook.com> | 2021-01-27 22:34:16 -0300 |
commit | bec35039b9a3448deca3a093cc9a7f283e54e55c (patch) | |
tree | 08836856195a572862664d45fb1f92ec69b5030e | |
parent | f0736436f8a0fd7fdddaa320a95b38107162e451 (diff) |
0.27.1: Added Zstandard supportv0.27.1
-rw-r--r-- | .SRCINFO | 4 | ||||
-rw-r--r-- | PKGBUILD | 4 | ||||
-rw-r--r-- | clifm.c | 280 | ||||
-rw-r--r-- | manpage | 14 |
4 files changed, 273 insertions, 29 deletions
@@ -1,7 +1,7 @@ pkgbase = clifm pkgdesc = The KISS file manager: cli-based, ultra-lightweight, and lightning fast - pkgver = 0.27.0 - pkgrel = 2 + pkgver = 0.27.1 + pkgrel = 1 url = https://github.com/leo-arch/clifm arch = any license = GPL2 @@ -1,8 +1,8 @@ # Maintainer: archcrack <johndoe.arch@outlook.com> pkgname=clifm -pkgver=0.27.0 -pkgrel=2 +pkgver=0.27.1 +pkgrel=1 pkgdesc="The KISS file manager: cli-based, ultra-lightweight, and lightning fast" arch=(any) url="https://github.com/leo-arch/clifm" @@ -151,7 +151,7 @@ in FreeBSD, but is deprecated */ /* If no formatting, puts (or write) is faster than printf */ /* #define CLEAR puts("\x1b[c") */ #define CLEAR write(STDOUT_FILENO, "\ec", 3) -#define VERSION "0.27.0" +#define VERSION "0.27.1" #define AUTHOR "L. Abramovich" #define CONTACT "johndoe.arch@outlook.com" #define WEBSITE "https://github.com/leo-arch/clifm" @@ -390,6 +390,7 @@ int mtime_sort(const struct dirent **a, const struct dirent **b); int bulk_rename(char **args); int archiver(char **args, char mode); +int zstandard(char *in_file, char *out_file, char mode, char op); int is_compressed(char *file); /* Still under development */ @@ -1128,7 +1129,9 @@ is_compressed(char *file) int compressed = 0; if (access(ARCHIVER_TMP_FILE, F_OK) == 0) { + file_fp = fopen(ARCHIVER_TMP_FILE, "r"); + if (file_fp) { char line[255] = ""; fgets(line, sizeof(line), file_fp); @@ -1152,11 +1155,129 @@ is_compressed(char *file) } int +zstandard(char *in_file, char *out_file, char mode, char op) +/* If MODE is 'c', compress IN_FILE producing a zstandard compressed + * file named OUT_FILE. If MODE is 'd', extract, test or get + * information about IN_FILE. Returns zero on success and one on + * error */ +{ + int exit_status = EXIT_SUCCESS; + + char *deq_file = dequote_str(in_file, 0); + + if (!deq_file) { + fprintf(stderr, "archiver: '%s': Error dequoting file\n", + in_file); + return EXIT_FAILURE; + } + + if (mode == 'c') { + + if (out_file) { + char *cmd[] = { "zstd", "-zo", out_file, deq_file, NULL }; + if (launch_execve(cmd, FOREGROUND) != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + } + + else { + char *cmd[] = { "zstd", "-z", deq_file, NULL }; + if (launch_execve(cmd, FOREGROUND) != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + } + + free(deq_file); + return exit_status; + } + + /* mode == 'd' */ + + /* op is non-zero when multiple files, including at least one + * zst file, are passed to the archiver function */ + if (op != 0) { + char option[3] = ""; + + switch(op) { + case 'e': strcpy(option, "-d"); break; + case 't': strcpy(option, "-t"); break; + case 'i': strcpy(option, "-l"); break; + } + + char *cmd[] = { "zstd", option, deq_file, NULL }; + + exit_status = launch_execve(cmd, FOREGROUND); + + free(deq_file); + + if (exit_status != EXIT_SUCCESS) + return EXIT_FAILURE; + + return EXIT_SUCCESS; + } + + + printf("%s[e]%sxtract %s[t]%sest %s[i]%snfo %s[q]%suit\n", + bold, NC, bold, NC, bold, NC, bold, NC); + + char *operation = (char *)NULL; + + while (!operation) { + operation = rl_no_hist(_("Operation: ")); + + if (!operation) + continue; + + if (operation && (!operation[0] || operation[1] != '\0')) { + free(operation); + operation = (char *)NULL; + continue; + } + + switch(*operation) { + case 'e': { + char *cmd[] = { "zstd", "-d", deq_file, NULL }; + if (launch_execve(cmd, FOREGROUND) != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + } + break; + + case 't': { + char *cmd[] = { "zstd", "-t", deq_file, NULL }; + if (launch_execve(cmd, FOREGROUND) != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + } + break; + + case 'i': { + char *cmd[] = { "zstd", "-l", deq_file, NULL }; + if (launch_execve(cmd, FOREGROUND) != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + } + break; + + case 'q': + free(operation); + free(deq_file); + return EXIT_SUCCESS; + + default: + free(operation); + operation = (char *)NULL; + break; + } + } + + free(operation); + free(deq_file); + + return exit_status; +} + +int archiver(char **args, char mode) -/* Handle archives or compressed files (ARGS) according to MODE: 'c' - * for compression and 'd' for decompression (including listing, - * extracting, repacking, and mounting). Returns zero on success and - * one on error */ +/* Handle archives and/or compressed files (ARGS) according to MODE: + * 'c' for archiving/compression, and 'd' for dearchiving/decompression + * (including listing, extracting, repacking, and mounting). Returns + * zero on success and one on error */ { size_t i; int uncompressed = 0, exit_status = EXIT_SUCCESS; @@ -1167,15 +1288,16 @@ archiver(char **args, char mode) if (mode == 'c') { /* ################################## - * # COMPRESSION # + * # 1 - COMPRESSION # * ##################################*/ - /* Ask for archive name */ - puts(_("Use extension to specify archive type.\n" + /* Get archive name/type */ + + puts(_("Use extension to specify archive/compression type.\n" "Defaults to .tar.gz")); char *name = (char *)NULL; while (!name) { - name = rl_no_hist(_("Archive name ('q' to quit): ")); + name = rl_no_hist(_("Filename ('q' to quit): ")); if (!name) continue; @@ -1192,6 +1314,43 @@ archiver(char **args, char mode) } } + /* ########################## + * # ZSTANDARD # + * ########################## */ + + char *ret = strrchr(name, '.'); + if (strcmp(ret, ".zst") == 0) { + + /* Multiple files */ + if (args[2]) { + + printf("\n%sNOTE%s: Zstandard does not support " + "compression of multiple files into one single " + "compressed file. Files will be compressed rather " + "into multiple compressed files using original " + "filenames\n", bold, NC); + + for (i = 1; args[i]; i++) { + if (zstandard(args[i], NULL, 'c', 0) + != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + } + } + + /* Only one file */ + else + exit_status = zstandard(args[1], name, 'c', 0); + + free(name); + + return exit_status; + } + + + /* ########################## + * # NO ZSTANDARD # + * ########################## */ + /* Escape the string, if needed */ char *esc_name = escape_str(name); free(name); @@ -1208,6 +1367,7 @@ archiver(char **args, char mode) size_t cmd_len = strlen(esc_name) + 10 + ((!ext_ok) ? 8 : 0); cmd = (char *)xcalloc(cmd_len, sizeof(char)); + /* If name has no extension, add the default */ sprintf(cmd, "atool -a %s%s", esc_name, (!ext_ok) ? ".tar.gz" : ""); @@ -1228,12 +1388,99 @@ archiver(char **args, char mode) return exit_status; } + /* mode == 'd' */ /* ################################## - * # DECOMPRESSION # + * # 2 - DECOMPRESSION # * ##################################*/ + /* Check if we have at least one Zstandard file */ + + int zst_index = -1; + size_t files_num = 0; + + for (i = 1; args[i]; i++) { + files_num++; + if (args[i][strlen(args[i]) -1] == 't') { + char *ret = strrchr(args[i], '.'); + if (ret) { + if (strcmp(ret, ".zst") == 0) + zst_index = i; + } + } + } + + /* ########################## + * # ZSTANDARD # + * ########################## */ + + if (zst_index != -1) { + + /* Multiple files */ + if (files_num > 1) { + + printf("%sNOTE%s: Using Zstandard\n", bold, NC); + printf("%s[e]%sxtract %s[t]%sest %s[i]%snfo %s[q]%suit\n", + bold, NC, bold, NC, bold, NC, bold, NC); + + char *operation = (char *)NULL; + char sel_op = 0; + while(!operation) { + operation = rl_no_hist("Operation: "); + + if (!operation) + continue; + + if (operation && (!operation[0] + || operation[1] != '\0')) { + free(operation); + operation = (char *)NULL; + continue; + } + + switch(*operation) { + case 'e': + case 't': + case 'i': + sel_op = *operation; + break; + + case 'q': + free(operation); + return EXIT_SUCCESS; + + default: + free(operation); + operation = (char *)NULL; + break; + } + } + + for (i = 1; args[i]; i++) { + if (zstandard(args[i], NULL, 'd', sel_op) + != EXIT_SUCCESS); + exit_status = EXIT_FAILURE; + } + + free(operation); + return exit_status; + } + + /* Just one file */ + else { + if (zstandard(args[zst_index], NULL, 'd', 0) != EXIT_SUCCESS) + exit_status = EXIT_FAILURE; + + return exit_status; + } + } + + + /* ########################## + * # NO ZSTANDARD # + * ########################## */ + /* 1) Get operation to be performed */ printf(_("%s[e]%sxtract %s[E]%sxtract-to-dir %s[l]%sist " "%s[m]%sount %s[r]%sepack %s[q]%suit\n"), bold, NC, bold, @@ -1241,7 +1488,6 @@ archiver(char **args, char mode) char *operation = (char *)NULL; char sel_op = 0; - size_t files_num = 0; while (!operation) { operation = rl_no_hist(_("Operation: ")); @@ -1317,7 +1563,7 @@ archiver(char **args, char mode) if (ret == 1) { fprintf(stderr, _("archiver: '%s': Not an " - "archive\n"), args[i]); + "archive/compressed file\n"), args[i]); continue; } @@ -1337,8 +1583,6 @@ archiver(char **args, char mode) /* Dequote filenames, if neccessary */ for (i = 1; args[i]; i++) { - files_num++; - if (strchr(args[i], '\\')) { char *deq_name = dequote_str(args[i], 0); @@ -1392,7 +1636,7 @@ archiver(char **args, char mode) if (ret == 1) { fprintf(stderr, _("archiver: '%s': Not an " - "archive\n"), args[i]); + "archive/compressed file\n"), args[i]); continue; } @@ -1455,7 +1699,7 @@ archiver(char **args, char mode) if (ret == 1) { fprintf(stderr, _("archiver: '%s': Not an " - "archive\n"), args[i]); + "archive/compressed file\n"), args[i]); continue; } @@ -1520,12 +1764,12 @@ archiver(char **args, char mode) /* ########## REPACK ############## */ case 'r': { - /* Ask for new archive format */ + /* Ask for new archive/compression format */ puts("Enter 'q' to quit"); char *format = (char *)NULL; while (!format) { - format = rl_no_hist(_("New archive format " + format = rl_no_hist(_("New format " "(Ex: .tar.xz): ")); if (!format) continue; @@ -51,7 +51,7 @@ List of CliFM features: 20) Resource opener 21) Multiple sorting methods and reverse sorting 22) Bulk rename - 23) Archives support + 23) Archiving and compression support .SH RATIONALE When it comes to software, Unix/GNU-Linux is no doubt the land of Freedom, and Freedom, so to say, is the elder sister of Choice and Alternative. Now, regarding File Managers (FM), broadly understood as a computer program providing a user interface to manage files and directories, we either stick to the CLI or Command Line Interface (the Linux built-in console or a terminal emulator running a bare shell) or choose rather some kind of graphical alternative (be it a GUI program, in the strictest sense, or a curses-based one). In between, however, there is nothing, or at least, almost nothing. But as the old Italian saying goes: "There is no two without three". @@ -182,9 +182,9 @@ rename at once all files passed as arguments to the function. It accepts single .TP .B ac, ad \fRELN/FILE ... n -compress and decompress one or multiple files and/or directories. The archiver function brings two modes: \fBac\fR, to generate archives or compressed files, and \fBad\fR, to decompress archives, either just listing, extracting, recompressing, or mounting their content. In this latter case, the mountpoint used automatically is \fI$HOME/.config/clifm/PROFILE/mounts/ARCHIVE_NAME\fR. The function accepts single and multiple filenames, wildcards, ELN ranges, and the 'sel' keyword. For example: 'ac sel', 'ac 4-25 myfile', or 'ad *.tar.gz'. +archive/compress and dearchive/decompress one or multiple files and/or directories. The archiver function brings two modes: \fBac\fR, to generate archives or compressed files, and \fBad\fR, to decompress or dearchive files, either just listing, extracting, recompressing, or mounting their content. In this latter case, the mountpoint used automatically is \fI$HOME/.config/clifm/PROFILE/mounts/ARCHIVE_NAME\fR. The function accepts single and multiple filenames, wildcards, ELN ranges, and the 'sel' keyword. For example: 'ac sel', 'ac 4-25 myfile', or 'ad *.tar.gz'.Multiple archive/compression formats are supported, including Zstandard. .sp -The archive mount function depends on \fBarchivemount\fR, while the remaining functions depend on \fBatool\fR and other third-party utilities for achive formats support, for example, \fBp7zip\fR. For more information consult \fBatool(1)\fR and \fBarchivemount(1)\fR. +The archive mount function depends on \fBarchivemount\fR, while the remaining functions depend on \fBatool\fR and other third-party utilities for achive formats support, for example, \fBp7zip\fR. For more information consult \fBatool(1)\fR, \fBarchivemount(1)\fR, and \fBzstd(1)\fR. .TP .B b, back \fR[h, hist] [clear] [!ELN] @@ -573,8 +573,8 @@ The file contains a series of fields separated by a colon in the following way: \fBMessages log file:\fR \fI~/.config.clifm/profile_name/messages.cfm\fR A file containing a list of system messages, either errors, warnings, or simple notices. The messages log format is: [date] message. -.SH AUTHOR -L.M. Abramovich (https://github.com/leo-arch) +.SH BUGS AND FEATURE REQUESTS +Report at: https://github.com/leo-arch/clifm/issues -.SH BUG REPORTS -johndoe.arch@outlook.com +.SH AUTHOR +L. M. Abramovich |