From 6948f210ed443f8153e0ba751e77bec8a0c6c8d4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 May 2010 04:18:13 +0200 Subject: *: teach tar et. al. to understand .xz by heart function old new delta unpack_xz_stream - 4126 +4126 setup_unzip_on_fd 80 150 +70 open_zipped 113 131 +18 unpack_unxz 5 12 +7 send_tree 360 353 -7 unpack_xz_stream_stdin 3953 - -3953 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 3/1 up/down: 4221/-3960) Total: 261 bytes Signed-off-by: Denys Vlasenko --- libbb/read.c | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) (limited to 'libbb') diff --git a/libbb/read.c b/libbb/read.c index f3af144f0..cd6bbeb13 100644 --- a/libbb/read.c +++ b/libbb/read.c @@ -305,22 +305,26 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) return buf; } +/* Used by e.g. rpm which gives us a fd without filename, + * thus we can't guess the format from filename's extension. + */ #if ZIPPED -int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) +void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) { const int fail_if_not_detected = 1; - unsigned char magic[2]; -#if BB_MMU + unsigned char magic[8]; + int offset = -2; +# if BB_MMU IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); enum { xformer_prog = 0 }; -#else +# else enum { xformer = 0 }; const char *xformer_prog; -#endif +# endif /* .gz and .bz2 both have 2-byte signature, and their * unpack_XXX_stream wants this header skipped. */ - xread(fd, &magic, 2); + xread(fd, magic, 2); if (ENABLE_FEATURE_SEAMLESS_GZ && magic[0] == 0x1f && magic[1] == 0x8b ) { @@ -341,28 +345,41 @@ int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) # endif goto found_magic; } -// TODO: xz format support. rpm adopted it, "rpm -i FILE.rpm" badly needs this. -// Signature: 0xFD, '7', 'z', 'X', 'Z', 0x00 -// More info at: http://tukaani.org/xz/xz-file-format.txt + if (ENABLE_FEATURE_SEAMLESS_XZ + && magic[0] == 0xfd && magic[1] == '7' + ) { + /* .xz signature: 0xfd, '7', 'z', 'X', 'Z', 0x00 */ + /* More info at: http://tukaani.org/xz/xz-file-format.txt */ + offset = -6; + xread(fd, magic + 2, 4); + if (strcmp((char*)magic + 2, "zXZ") == 0) { +# if BB_MMU + xformer = unpack_xz_stream; +# else + xformer_prog = "unxz"; +# endif + xlseek(fd, offset, SEEK_CUR); + goto found_magic; + } + } /* No known magic seen */ if (fail_if_not_detected) bb_error_msg_and_die("no gzip" IF_FEATURE_SEAMLESS_BZ2("/bzip2") + IF_FEATURE_SEAMLESS_XZ("/xz") " magic"); - xlseek(fd, -2, SEEK_CUR); - return fd; + xlseek(fd, offset, SEEK_CUR); + return; found_magic: # if !BB_MMU /* NOMMU version of open_transformer execs * an external unzipper that wants * file position at the start of the file */ - xlseek(fd, -2, SEEK_CUR); + xlseek(fd, offset, SEEK_CUR); # endif open_transformer(fd, xformer, xformer_prog); - - return fd; } #endif /* ZIPPED */ @@ -380,12 +397,14 @@ int FAST_FUNC open_zipped(const char *fname) sfx = strrchr(fname, '.'); if (sfx) { - if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, ".lzma") == 0) + sfx++; + if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0) /* .lzma has no header/signature, just trust it */ open_transformer(fd, unpack_lzma_stream, "unlzma"); else - if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0) - || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0) + if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0) + || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0) + || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0) ) { setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); } -- cgit v1.2.3-55-g6feb From 11bcf4b22449d08b61617183c1951db98457653a Mon Sep 17 00:00:00 2001 From: Tomas Heinrich Date: Tue, 1 Jun 2010 08:33:18 +0200 Subject: lineedit: fix column display for wide and combining chars in TAB completion function old new delta unicode_strwidth - 20 +20 read_line_input 4945 4953 +8 unicode_strlen 31 - -31 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 28/-31) Total: -3 bytes Signed-off-by: Tomas Heinrich Signed-off-by: Denys Vlasenko --- include/unicode.h | 6 +++++- libbb/lineedit.c | 9 ++++++--- libbb/unicode.c | 17 ++++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) (limited to 'libbb') diff --git a/include/unicode.h b/include/unicode.h index eaf67c833..e9e2bd14a 100644 --- a/include/unicode.h +++ b/include/unicode.h @@ -23,7 +23,8 @@ enum { #if !ENABLE_UNICODE_SUPPORT -# define unicode_strlen(string) strlen(string) +# define unicode_strlen(string) strlen(string) +# define unicode_strwidth(string) strlen(string) # define unicode_status UNICODE_OFF # define init_unicode() ((void)0) @@ -49,7 +50,10 @@ enum { # define ENABLE_UNICODE_BIDI_SUPPORT 0 # endif +/* Number of unicode chars. Falls back to strlen() on invalid unicode */ size_t FAST_FUNC unicode_strlen(const char *string); +/* Width on terminal */ +size_t FAST_FUNC unicode_strwidth(const char *string); enum { UNI_FLAG_PAD = (1 << 0), }; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 18664b8c1..8a2ea7974 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -992,7 +992,7 @@ static void showfiles(void) /* find the longest file name - use that as the column width */ for (row = 0; row < nrows; row++) { - l = unicode_strlen(matches[row]); + l = unicode_strwidth(matches[row]); if (column_width < l) column_width = l; } @@ -1012,10 +1012,13 @@ static void showfiles(void) for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) { printf("%s%-*s", matches[n], - (int)(column_width - unicode_strlen(matches[n])), "" + (int)(column_width - unicode_strwidth(matches[n])), "" ); } - puts(matches[n]); + if (ENABLE_UNICODE_SUPPORT) + puts(printable_string(NULL, matches[n])); + else + puts(matches[n]); } } diff --git a/libbb/unicode.c b/libbb/unicode.c index b2c28239b..d6fcf7a43 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -25,13 +25,15 @@ uint8_t unicode_status; void FAST_FUNC init_unicode(void) { - /* In unicode, this is a one character string */ static const char unicode_0x394[] = { 0xce, 0x94, 0 }; + size_t width; if (unicode_status != UNICODE_UNKNOWN) return; - - unicode_status = unicode_strlen(unicode_0x394) == 1 ? UNICODE_ON : UNICODE_OFF; + /* In unicode, this is a one character string */ +// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused + width = mbstowcs(NULL, unicode_0x394, INT_MAX); + unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF); } #else @@ -954,6 +956,7 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) /* The rest is mostly same for libc and for "homegrown" support */ +#if 0 // UNUSED size_t FAST_FUNC unicode_strlen(const char *string) { size_t width = mbstowcs(NULL, string, INT_MAX); @@ -961,6 +964,14 @@ size_t FAST_FUNC unicode_strlen(const char *string) return strlen(string); return width; } +#endif + +size_t FAST_FUNC unicode_strwidth(const char *string) +{ + uni_stat_t uni_stat; + printable_string(&uni_stat, string); + return uni_stat.unicode_width; +} static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char *src, unsigned width, int flags) { -- cgit v1.2.3-55-g6feb