From ff2d609c9b5f5f57f3331e5593e8fe87c01654dd Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Thu, 12 Aug 2021 16:36:35 -0700 Subject: [PATCH 01/11] add close_fds=False in subprocess.Popen() to allow process substitution in magic syntax. Also check for too many open files exception --- jc/cli.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index 4dafde69..a756eb91 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -466,7 +466,11 @@ def magic_parser(args): def run_user_command(command): """Use subprocess to run the user's command. Returns the STDOUT, STDERR, and the Exit Code as a tuple.""" - proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + proc = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=False, + universal_newlines=True) stdout, stderr = proc.communicate() return ( @@ -560,6 +564,13 @@ def main(): jc.utils.error_message(f'"{run_command_str}" command could not be found. For details use the -d or -dd option.') sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) + except OSError: + if debug: + raise + else: + jc.utils.error_message(f'"{run_command_str}" command could not be run due to too many open files. For details use the -d or -dd option.') + sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT)) + except Exception: if debug: raise From 7cc168f6409af13fda815d0d2a6db25b7c9ba367 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Thu, 12 Aug 2021 16:55:07 -0700 Subject: [PATCH 02/11] add comment --- jc/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index a756eb91..b79b50be 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -469,7 +469,7 @@ def run_user_command(command): proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - close_fds=False, + close_fds=False, # Allows inheriting file descriptors. Useful for process substitution universal_newlines=True) stdout, stderr = proc.communicate() From fdbe3e05f323c95687a1137983f9623911008ca2 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 14:19:26 -0700 Subject: [PATCH 03/11] fix issue with globs not including filenames with spaces with magic syntax (introduced during switch to use subprocess to grab process exit code). No longer need to shlex quote arguments. --- jc/cli.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jc/cli.py b/jc/cli.py index b79b50be..40e74d3d 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -6,7 +6,6 @@ import sys import os import os.path import re -import shlex import importlib import textwrap import signal @@ -415,8 +414,7 @@ def magic_parser(args): if len(args) <= 1 or args[1].startswith('--'): return False, None, None, [] - # correctly parse escape characters and spaces with shlex - args_given = ' '.join(map(shlex.quote, args[1:])).split() + args_given = args[1:] options = [] # find the options From 45e6e06be581f787f707e3f5645129c713478d16 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 14:19:45 -0700 Subject: [PATCH 04/11] add glob and process substitution fixes --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index da0729a6..14d83a40 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,10 @@ jc changelog +20210813 v1.16.1 +- Note to Package Maintainers: please see note at 20210720 v1.16.0 +- Fix issue with process substitution with the magic syntax +- Fix issue with globs not including filenames with spaces with magic syntax + 20210720 v1.16.0 - Note to Package Maintainers: TL;DR: `/man/jc.1.gz` and `/jc/man/jc.1.gz` are deprecated and only `/man/jc.1` should be used. From 4c2912d3d5ec1fd2d5d891f2b3c58a33dd8572be Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 15:19:17 -0700 Subject: [PATCH 05/11] use shlex.join to quote run_command_str for better error messages --- jc/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index 40e74d3d..5c35d9a7 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -9,6 +9,7 @@ import re import importlib import textwrap import signal +import shlex import subprocess import json import jc @@ -547,7 +548,7 @@ def main(): # if magic syntax used, try to run the command and error if it's not found, etc. magic_stdout, magic_stderr, magic_exit_code = None, None, 0 if run_command: - run_command_str = ' '.join(run_command) + run_command_str = shlex.join(run_command) if valid_command: try: From 1f99d40cecc5d88a246f3558f71db376ebd885c6 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 15:19:31 -0700 Subject: [PATCH 06/11] fix filename with spaces for osx/bsd --- jc/parsers/stat.py | 4 ++-- .../osx-10.14.6/stat-filename-with-spaces.json | 1 + .../osx-10.14.6/stat-filename-with-spaces.out | 2 ++ tests/test_stat.py | 12 ++++++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/osx-10.14.6/stat-filename-with-spaces.json create mode 100644 tests/fixtures/osx-10.14.6/stat-filename-with-spaces.out diff --git a/jc/parsers/stat.py b/jc/parsers/stat.py index d071bf31..6ed8e6cc 100644 --- a/jc/parsers/stat.py +++ b/jc/parsers/stat.py @@ -169,7 +169,7 @@ import jc.utils class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.8' + version = '1.9' description = '`stat` command parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -322,7 +322,7 @@ def parse(data, raw=False, quiet=False): for line in cleandata: value = shlex.split(line) output_line = { - 'file': value[15], + 'file': ' '.join(value[15:]), 'unix_device': value[0], 'inode': value[1], 'flags': value[2], diff --git a/tests/fixtures/osx-10.14.6/stat-filename-with-spaces.json b/tests/fixtures/osx-10.14.6/stat-filename-with-spaces.json new file mode 100644 index 00000000..5b85c4f7 --- /dev/null +++ b/tests/fixtures/osx-10.14.6/stat-filename-with-spaces.json @@ -0,0 +1 @@ +[{"file":"file name with spaces.txt","unix_device":16777220,"inode":161929661,"flags":"-rw-r--r--","links":1,"user":"kbrazil","group":"staff","rdev":0,"size":0,"access_time":"Aug 13 15:03:52 2021","modify_time":"Aug 13 14:37:03 2021","change_time":"Aug 13 14:37:03 2021","birth_time":"Aug 13 14:37:03 2021","block_size":4096,"blocks":0,"unix_flags":"0","access_time_epoch":1628892232,"access_time_epoch_utc":null,"modify_time_epoch":1628890623,"modify_time_epoch_utc":null,"change_time_epoch":1628890623,"change_time_epoch_utc":null,"birth_time_epoch":1628890623,"birth_time_epoch_utc":null}] diff --git a/tests/fixtures/osx-10.14.6/stat-filename-with-spaces.out b/tests/fixtures/osx-10.14.6/stat-filename-with-spaces.out new file mode 100644 index 00000000..083d89fd --- /dev/null +++ b/tests/fixtures/osx-10.14.6/stat-filename-with-spaces.out @@ -0,0 +1,2 @@ +16777220 161929661 -rw-r--r-- 1 kbrazil staff 0 0 "Aug 13 15:03:52 2021" "Aug 13 14:37:03 2021" "Aug 13 14:37:03 2021" "Aug 13 14:37:03 2021" 4096 0 0 file name with spaces.txt + diff --git a/tests/test_stat.py b/tests/test_stat.py index 9d4c84ac..3f8ad60c 100644 --- a/tests/test_stat.py +++ b/tests/test_stat.py @@ -26,6 +26,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat.out'), 'r', encoding='utf-8') as f: self.osx_10_14_6_stat = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat-filename-with-spaces.out'), 'r', encoding='utf-8') as f: + self.osx_10_14_6_stat_filename_with_spaces = f.read() + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/stat.out'), 'r', encoding='utf-8') as f: self.freebsd12_stat = f.read() @@ -39,6 +42,9 @@ class MyTests(unittest.TestCase): with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat.json'), 'r', encoding='utf-8') as f: self.osx_10_14_6_stat_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/stat-filename-with-spaces.json'), 'r', encoding='utf-8') as f: + self.osx_10_14_6_stat_filename_with_spaces_json = json.loads(f.read()) + with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/stat.json'), 'r', encoding='utf-8') as f: self.freebsd12_stat_json = json.loads(f.read()) @@ -66,6 +72,12 @@ class MyTests(unittest.TestCase): """ self.assertEqual(jc.parsers.stat.parse(self.osx_10_14_6_stat, quiet=True), self.osx_10_14_6_stat_json) + def test_stat_filename_with_spaces_osx_10_14_6(self): + """ + Test 'stat' filename with spaces on OSX 10.14.6 + """ + self.assertEqual(jc.parsers.stat.parse(self.osx_10_14_6_stat_filename_with_spaces, quiet=True), self.osx_10_14_6_stat_filename_with_spaces_json) + def test_stat_freebsd12(self): """ Test 'stat /foo/*' on FreeBSD12 From 78caf7646baf5d35602fd76771443cd64bd783af Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 15:19:41 -0700 Subject: [PATCH 07/11] add stat fix --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 14d83a40..edd52ac9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ jc changelog - Note to Package Maintainers: please see note at 20210720 v1.16.0 - Fix issue with process substitution with the magic syntax - Fix issue with globs not including filenames with spaces with magic syntax +- Fix stat parser to properly handle filenames with spaces on macOS/BSD 20210720 v1.16.0 - Note to Package Maintainers: From 166aef7a022ed29862ab2e0702d53c591bb5cc77 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 15:22:33 -0700 Subject: [PATCH 08/11] version bump --- docs/parsers/stat.md | 2 +- jc/__init__.py | 2 +- jc/man/jc.1.gz | Bin 2699 -> 2700 bytes man/jc.1 | 2 +- man/jc.1.gz | Bin 2699 -> 2700 bytes setup.py | 2 +- 6 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/parsers/stat.md b/docs/parsers/stat.md index 350b25f5..3e62440b 100644 --- a/docs/parsers/stat.md +++ b/docs/parsers/stat.md @@ -193,4 +193,4 @@ Returns: ## Parser Information Compatibility: linux, darwin, freebsd -Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com) +Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com) diff --git a/jc/__init__.py b/jc/__init__.py index a1f56da0..07cd69d4 100644 --- a/jc/__init__.py +++ b/jc/__init__.py @@ -86,4 +86,4 @@ Module Example: """ name = 'jc' -__version__ = '1.16.0' +__version__ = '1.16.1' diff --git a/jc/man/jc.1.gz b/jc/man/jc.1.gz index 0643b709daa575408ea8a8705b76a739ecd8fd09..c857ff2bf6bedb935cedff874bc8a2b42d866703 100644 GIT binary patch delta 2600 zcmV+@3fJ|E6^s>sABzYGXYdwb0{?1bE-?U|S#59II1>KuUqKWLTmr;)(!&;e!S!&i zlWx76*g@=cTeL+(Nwm#G5>=9lqs9IBn-|KKjl>H2A@PuU=7q!Ia7gxMAH-cOPQ>fu z*C*ZM-?}IN6eqotH@y?_>W}GUEQS{&VMdI zRus}YoiBuc&V`GuF1+iZnKF(Q(4x?VO5h`kom-QMuk&})+1Y6Pb$&%sStV#7Q-oE8 zRZhV$yf!&nf_6dQgEplTvB|))=+sI)pF?rragSmq*9 zqI6(bRH5ub;`$r67*m*!dCvEtXD}-ObWDr%hf^(=}-*7fLCXkO0@K#7`}mz z)Rrvm!~(3!d*WbhygJ>rD>2~N+<4*2qA(VImnuy~RO-}gPzgS-Mafi4r`#b=X_)9v z?_K8#Wy<>b>__}vdgj}sDqi8g4yP&R;(Y=K)9Bm>a`b#?6Zm5=+> zynQ|x7S@!-22Ra=aJQ6+Sv45AV-L$xx+UR}*l#-`!jcQ*4qP1EX34L(0*_!J0){BC zqj$I?Db|o}=OHfFtrqp#d1EVPVY-FEIPW&TpynP=gv`^HcJ#bqdfjMY$tfp~#-lxd z+6#z;RI$Bvqebkh>tKgsj+IE%gZKjfbgaG!{IH+<&P1#XiT%)fT48^xs{c`@rFwo4 zsdT)bAQ2KWlF@$oDI1cyHW=&*0SQzaI5SBA1JwpL^MExi$uu)%&SNBMKR8z&7C6HL z-NN9DAB+YqOCc?SBC&UYXNM-~_BFqnxZ(8)|qMPb4wa^gQXlHTDkcyB6 z8!apx1w~5~Kne^SBvCEkBJ2L(f(S?f^nSdXC)#n0G1&s&Nw=-p*6|o!%NW-|(;hLd za zrrDH39W8>&IY&GEzQ}yQb!AbkU5$Lu7T6)a0F~;P&Vb)qjOAYN5-iQU`r4M zH5`8nW?Kr}($L=Tlh*_*0hE&i1u6<@G!w(g+4;0H$dfk(Hh&;e2tB4NlfRZKhodRp zfIM+sa-e#P9)j_PBNVkzxi69T@MvujR^7Xr*0(oiVPyt7Q3XvJpQmM#2<_`T7ZkPT z?THyw^5EnO5kQ6OCcq}jD+@_kfjKmO^bjB&UoeqI)=?{l&v$XJ(-}f+!-3QiW^U5d ztk5F$D6;~#hJWCLP3eBxp@py+^?GD)YwsOxS>5c16$={ySn=cNYTKFD4&yAxFq-Ql9A8+fri+^G??OJw56hUBbA`#;V^#qY zVS8n4vTo;P7C~C9o2(%;I~`csR@LK`R-NJyq7>3C`5YQnB{jLQO67Hd1$5^<-eL2~Kf<)))H)LdSnylO0-HHOLyj85I|_Cj(LnG*zBz+I*wHh;o4_63 zOlOnJaKS(A3^`U)6T>bLcDf=h7kCw%$%<~DL4P~lt_#Ttx_=il((x9VVzPtJ6$T?q zdNqI|3+hZM5^bT_G`4ybM%Wb>IxiplP%J-Ep#1V-a(UkG5hI>ptm^OR=m1kDJH-_F?In zCx6mH?yvk36vF|(O!;2I^~6os4B1&hXn$@@ufVvi1xkF5fWjaAOIs`~Tn&wi9nQ`U z98^k$g-lW#{&!`>Q_x!*OqLQ8E^3%am}Hzu$OwAZW`+A!7l_H%pceU zo2*QWrG!MFtd9Au2Haph-#JT>LUjX1h<~OH976_b5eqxwI^x4eFqoexFzGdF@twd4 zsf*u^KArt8-brxq+4}R8(r(}lK|c6+KA26h8X|MlDS8UmVx(YHP+5T)ju#`l^kOjn z9WfMz>Y0>FuRueD@j_Sm_nT?&X7;}O81~y!BOm9;Old}W*P>cF3geQ0aCvnB1%Lmv&Rf&) zgo_FJ7YNLSSglsQg)s{#LST>_dyUr{u|CF7W~AbMM@nEo&=V4w@BK69sT~>1T4Vio zM5jj>$>3)8VRGI16E^NjytDFeor;5dY~7hWqV|6mnbaw&gfemIec?{~{RJ$>GQ!UO zHX1gHkTND$pRY&1f0#l2UMWOXjO@4o delta 2599 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 delta 2599 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 J+}6t<007 Date: Fri, 13 Aug 2021 16:01:45 -0700 Subject: [PATCH 09/11] try/except for shlex.join since only available in python 3.8 --- jc/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index 5c35d9a7..9bd8f7ec 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -548,7 +548,10 @@ def main(): # if magic syntax used, try to run the command and error if it's not found, etc. magic_stdout, magic_stderr, magic_exit_code = None, None, 0 if run_command: - run_command_str = shlex.join(run_command) + try: + run_command_str = shlex.join(run_command) # python 3.8+ + except AttributeError: + run_command_str = join(run_command) # older python versions if valid_command: try: From 01e3764a9b6ba902aea522bf6b7005fd37b3acbb Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 16:03:46 -0700 Subject: [PATCH 10/11] fix join syntax --- jc/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/cli.py b/jc/cli.py index 9bd8f7ec..4876bd3c 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -551,7 +551,7 @@ def main(): try: run_command_str = shlex.join(run_command) # python 3.8+ except AttributeError: - run_command_str = join(run_command) # older python versions + run_command_str = ' '.join(run_command) # older python versions if valid_command: try: From 0dbd2702f6ab2640b2ccdea92411ac0789673e66 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Fri, 13 Aug 2021 17:17:51 -0700 Subject: [PATCH 11/11] reformat doc_text for nicer indentation --- jc/cli.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/jc/cli.py b/jc/cli.py index 4876bd3c..c4efee46 100644 --- a/jc/cli.py +++ b/jc/cli.py @@ -360,11 +360,10 @@ def help_doc(options): # load parser module just in time so we don't need to load all modules parser = parser_module(arg) compatible = ', '.join(parser.info.compatible) - doc_text = f'''{parser.__doc__} -Compatibility: {compatible} - -Version {parser.info.version} by {parser.info.author} ({parser.info.author_email}) -''' + doc_text = \ + f'{parser.__doc__}\n'\ + f'Compatibility: {compatible}\n\n'\ + f'Version {parser.info.version} by {parser.info.author} ({parser.info.author_email})\n' return doc_text