From 30fe994c6836810cf4330f16809e33a1a4565adc Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Sun, 8 Oct 2017 19:39:16 -0600 Subject: [PATCH] Add more logging and configurable levels --- sn_fuse.py | 15 ++++++++--- standardnotes_fs.py | 61 +++++++++++++++++++++++++++++++++------------ 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/sn_fuse.py b/sn_fuse.py index 1830fe9..b2e2c98 100644 --- a/sn_fuse.py +++ b/sn_fuse.py @@ -71,9 +71,14 @@ class StandardNotesFUSE(LoggingMixIn, Operations): path_parts = path.split('/') note_name = path_parts[1] note = self.notes[note_name] - text = note['text'][:offset] + data.decode() uuid = note['uuid'] + try: + text = note['text'][:offset] + data.decode() + except UnicodeError: + logging.error('Unable to parse non-unicode data.') + raise FuseOSError(errno.EIO) + self.item_manager.writeNote(uuid, text) return len(data) @@ -84,6 +89,7 @@ class StandardNotesFUSE(LoggingMixIn, Operations): # disallow hidden files (usually editor / OS files) if note_name[0] == '.': + logging.error('Creation of hidden files is disabled.') raise FuseOSError(errno.EPERM) now = datetime.utcnow().isoformat()[:-3] + 'Z' # hack @@ -103,6 +109,10 @@ class StandardNotesFUSE(LoggingMixIn, Operations): return 0 + def mkdir(self, path, mode): + logging.error('Creation of directories is disabled.') + raise FuseOSError(errno.EPERM) + def chmod(self, path, mode): return 0 @@ -112,9 +122,6 @@ class StandardNotesFUSE(LoggingMixIn, Operations): def destroy(self, path): return 0 - def mkdir(self, path, mode): - return 0 - def readlink(self, path): return 0 diff --git a/standardnotes_fs.py b/standardnotes_fs.py index 8b7f582..9ade603 100644 --- a/standardnotes_fs.py +++ b/standardnotes_fs.py @@ -14,7 +14,6 @@ from fuse import FUSE OFFICIAL_SERVER_URL = 'https://sync.standardnotes.org' APP_NAME = 'standardnotes-fs' -logging.basicConfig(level=logging.DEBUG) # path settings cfg_env = os.environ.get('SN_FS_CONFIG_PATH') @@ -28,9 +27,13 @@ def parse_options(): help='Standard Notes username to log in with') parser.add_argument('--password', help='Standard Notes password to log in with\n' - 'NOTE: It is NOT recommended to use this! The\n' - ' password may be stored in history, so\n' + 'NOTE: It is NOT recommended to use this option!\n' + ' The password may be stored in history, so\n' ' use the password prompt instead.') + parser.add_argument('-v', '--verbosity', action='count', + help='output verbosity -v or -vv (implies --foreground)') + parser.add_argument('--foreground', action='store_true', + help='run standardnotes-fs in the foreground') parser.add_argument('--sync-url', help='URL of Standard File sync server. Defaults to:\n' ''+OFFICIAL_SERVER_URL) @@ -48,6 +51,15 @@ def main(): config = ConfigParser() keys = {} + # configure logging + if args.verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif args.verbosity == 2: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.CRITICAL) + if args.verbosity: args.foreground = True + config_file = args.config if args.config else CONFIG_FILE config_file = pathlib.Path(config_file) @@ -55,9 +67,9 @@ def main(): if args.logout: try: config_file.unlink() - print('Config file deleted.') + print('Config file deleted and logged out.') except OSError: - print('Already logged out.') + logging.info('Already logged out.') sys.exit(0) # make sure mountpoint is specified @@ -69,17 +81,21 @@ def main(): if not args.no_config_file: try: config_file.parent.mkdir(mode=0o0700, parents=True, exist_ok=True) + log_msg = 'Using config directory "%s".' + logging.info(log_msg % str(config_file.parent)) except OSError: - err_msg = 'Error creating directory "%s".' - logging.critical(err_msg % str(config_file.parent)) + log_msg = 'Error creating config file directory "%s".' + logging.critical(log_msg % str(config_file.parent)) sys.exit(1) try: with config_file.open() as f: config.read_file(f) + log_msg = 'Loaded config file "%s".' + logging.info(log_msg % str(config_file)) except OSError: - err_msg = 'Unable to read config file "%s".' - logging.info(err_msg % str(config_file)) + log_msg = 'Unable to read config file "%s".' + logging.info(log_msg % str(config_file)) # figure out all login params if args.sync_url: @@ -88,6 +104,8 @@ def main(): sync_url = config.get('user', 'sync_url') else: sync_url = OFFICIAL_SERVER_URL + log_msg = 'Using sync URL "%s".' + logging.info(log_msg % sync_url) if config.has_option('user', 'username') \ and config.has_section('keys') \ @@ -107,15 +125,14 @@ def main(): if not keys: keys = sn_api.genKeys(password) sn_api.signIn(keys) + log_msg = 'Successfully logged into account "%s".' + logging.info(log_msg % username) login_success = True except: - err_msg = 'Failed to log into account "%s".' - logging.critical(err_msg % username) + log_msg = 'Failed to log into account "%s".' + logging.critical(log_msg % username) login_success = False - if login_success: - fuse = FUSE(StandardNotesFUSE(sn_api), args.mountpoint, foreground=True, nothreads=True) - # write settings back if good, clear if not if not args.no_config_file: config.read_dict(dict(user=dict(sync_url=sync_url, username=username), @@ -124,9 +141,21 @@ def main(): with config_file.open(mode='w+') as f: if login_success: config.write(f) + log_msg = 'Config written to file "%s".' + logging.info(log_msg % str(config_file)) + else: + log_msg = 'Clearing config file "%s".' + logging.info(log_msg % username) + config_file.chmod(0o600) except OSError: - err_msg = 'Unable to write config file "%s".' - logging.error(err_msg % str(config_file)) + log_msg = 'Unable to write config file "%s".' + logging.error(log_msg % str(config_file)) + + if login_success: + logging.info('Starting FUSE filesystem.') + fuse = FUSE(StandardNotesFUSE(sn_api), args.mountpoint, foreground=args.foreground, nothreads=True) + + logging.info('Exiting.') if __name__ == '__main__': main()