From 47282c43b95dd75f9957946045d6ce5ee020f93b Mon Sep 17 00:00:00 2001 From: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Thu, 23 Dec 2021 08:49:04 +0100 Subject: [PATCH] Initial remote interface error message localization support (#555) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Extracted code * Initial support for (optional) recursive image file listings * Manpage update * Added support for image file filter * Updated filtering * Made image scan depth configurable * Code cleanup, initial support for creating nested file * Check for existing folder * Cleanup * Cleanup * Copy/rename/create * Updated delete operation * Delete empty folders * Code cleanup * Fixed typo * Check image file nesting level * Updated error handling * Fixed warning * Renaming * Error message update * Interface comment updates * Added depth to image info * Fixed scan depth check * Squashed commit of the following: commit 94786aec54c589c080dcec3b18b388a17de64ae3 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Tue Dec 21 08:43:21 2021 +0100 Added support for operation meta data, code cleanup (#534) * Added messages * Comment update * Interface update * Support for localized descriptions * Sort operations * Completed meta data * rasctl -s returns operation meta data * Manpage update * Type update * Comment update * Description updates * Comment update * Added convenience method * Added convenience method * Code cleanup * Comment update * Display permitted values * For completeness sake added permitted boolean values * Added support for default value * Removed redundant message field * Description update * Description upddate * Squashed commit of the following: commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce Author: Uwe Seimet Date: Sat Dec 18 12:43:14 2021 +0100 The data type is implicit commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c Author: Uwe Seimet Date: Sat Dec 18 12:37:49 2021 +0100 Renaming commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089 Author: Uwe Seimet Date: Sat Dec 18 12:29:54 2021 +0100 Comment update commit 5f699aad2f835f72accdb445d1e59f094aeb108f Author: Uwe Seimet Date: Sat Dec 18 12:24:25 2021 +0100 Signature update commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e Author: Uwe Seimet Date: Sat Dec 18 12:22:45 2021 +0100 Signature update commit a8148ef802ca809e5a305d2caa69856c9033d932 Author: Uwe Seimet Date: Sat Dec 18 12:16:46 2021 +0100 Comment update commit ce685a92d4827e131d80d10ecd56e2b3baf173f8 Author: Uwe Seimet Date: Sat Dec 18 12:15:46 2021 +0100 Use map instead of list commit 454c0438f3589904f5dbe5253963dd200ea416dd Author: Uwe Seimet Date: Sat Dec 18 10:47:36 2021 +0100 Updated size check commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2 Author: Uwe Seimet Date: Sat Dec 18 01:23:43 2021 +0100 Initial improvements * Default value update * Comment update * Comment update * Map operations by ordinal * Added safeguard against unknown operations * Added cast * Data type update * Sort map by operation name * Renaming * Code cleanup * Comment update * Renaming * Comment update * Description updates * Fixed typo * Added operation * Logging update * Interface comment update * Fixed typo * Aded operation parameters * Updated handling of mandatory parameters * Updated assertion handling * Added missing condition * Removed duplicate cod3 * Code cleanup * Logging update * Removed duplicate code * Code cleanup * Squashed commit of the following: commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup * Shutdown functionality is only available if started with root permissions * Only restrict shutdown parameters, not everything if not root * Updated operation count check commit 693ade296756ee8e480e75663a873e4a35829034 Author: Daniel Markstedt Date: Mon Dec 20 12:04:23 2021 -0800 Bump Macproxy version to 21.12.2 (#550) commit 958fb95908f2d8cdf13c02d827f2d14f6011170e Author: akuker <34318535+akuker@users.noreply.github.com> Date: Mon Dec 20 12:50:14 2021 -0600 Adjust bus settle delay to match SCSI standard (#544) * Move the GCC v10 compiler flags into makefile instead of easyinstall.sh * #504 - Update the bus settle time to match the SCSI standard Co-authored-by: RaSCSI User commit 200bc7251f2395842df7c7be9b90f2b44940a9d4 Author: Daniel Markstedt Date: Mon Dec 20 06:20:22 2021 -0800 More helpful error message when IP does not resolve for OLED screen (#541) * More helpful error message * Remove confusing fallback IP * Tweak message commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup commit ec31198d83f5ff7400d74d7acf08c832998deb91 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sun Dec 19 11:54:10 2021 +0100 Optional authentication by access token (#529) * Added authentication by access token * No authentication is required for getting the rascsi version * Added comment * Interface description update * Manpage update * Added error code * Enum value update (backwards compatible) * Error code update * Error code update * Added CHECK_AUTHENTICATION * Comment update * VERSION_INFO also requires authentication * rasctl: Made token an optional parameter for -P * Fixed interface comment commit e32211ef737d1a435ee8ca1d7244b3609202b28f Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sun Dec 19 11:49:17 2021 +0100 Recursive image file scan and image file filter (#532) * Extracted code * Initial support for (optional) recursive image file listings * Manpage update * Added support for image file filter * Updated filtering * Made image scan depth configurable * Squashed commit of the following: commit 192b14169f7b3f433d23d4306b60ae1aff7e3c96 Author: Uwe Seimet Date: Tue Dec 21 09:19:05 2021 +0100 Meta data update commit b319d726018a8fef01b76c19cd600aa70891568f Author: Uwe Seimet Date: Tue Dec 21 09:02:39 2021 +0100 Squashed commit of the following: commit 0ab4918c5a59f978f48cf26f431ff809e9ddae33 Author: Uwe Seimet Date: Mon Dec 20 16:52:03 2021 +0100 Scan depth determines availability of folder filter commit 16590cc4e4420a348fae610d749082c9d718be0a Author: Uwe Seimet Date: Mon Dec 20 15:47:08 2021 +0100 Updated operation count check commit 82f7c99755f535a7a5c30fe66e377705c5306faa Author: Uwe Seimet Date: Mon Dec 20 15:41:32 2021 +0100 Only restrict shutdown parameters, not everything if not root commit 9bd50d37b11c48b2130e4f6e66d12def88ddc38f Author: Uwe Seimet Date: Mon Dec 20 15:28:08 2021 +0100 Shutdown functionality is only available if started with root permissions commit aa5f3331abf4c178e8ce738c14fd584bd41d1b94 Author: Uwe Seimet Date: Mon Dec 20 10:26:14 2021 +0100 Squashed commit of the following: commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup commit a1f4b28f92bd9f7cdba18c04f61d3721fc7c720f Author: Uwe Seimet Date: Sun Dec 19 21:50:15 2021 +0100 Comment update commit 9cbc06caf5f00ce85e0f7f984c871ed614e2e483 Author: Uwe Seimet Date: Sun Dec 19 21:49:09 2021 +0100 Option update commit c4aa39c2285c5c72e2ea28ad749f5670dd10e89f Author: Uwe Seimet Date: Sun Dec 19 21:46:37 2021 +0100 Merged feature_folder_filter commit ea386fc74cbd64f19a7805d16c19f08f278739f3 Author: Uwe Seimet Date: Sun Dec 19 19:05:07 2021 +0100 Code cleanup commit 17c320113564fa2f0f2f11c1fe2e8b0048be2f48 Author: Uwe Seimet Date: Sun Dec 19 19:03:13 2021 +0100 Removed duplicate code commit 296f816dd3bc632efd11cda4b181362fb89e14e3 Author: Uwe Seimet Date: Sun Dec 19 18:40:49 2021 +0100 Logging update commit 73e0df85576932f2a99df5c8472a6922a6ed9e95 Author: Uwe Seimet Date: Sun Dec 19 17:28:02 2021 +0100 Code cleanup commit 405dbb034cf7775e069e5db9751f007587318558 Author: Uwe Seimet Date: Sun Dec 19 17:13:40 2021 +0100 Removed duplicate cod3 commit c7c168a9420ea43f3b3dd003a5d75a928e8f66c5 Author: Uwe Seimet Date: Sun Dec 19 17:08:02 2021 +0100 Added missing condition commit 6af5394f7879854b12d341c4b6c7ac1b06302494 Author: Uwe Seimet Date: Sun Dec 19 16:16:12 2021 +0100 Updated assertion handling commit 632fe1acd81fa27c096ff6190b5082717e3b3f02 Author: Uwe Seimet Date: Sun Dec 19 14:33:01 2021 +0100 Updated handling of mandatory parameters commit a4e0d506c6a48641b827bc88590d0b416ae2513c Author: Uwe Seimet Date: Sun Dec 19 14:14:09 2021 +0100 Aded operation parameters commit fc783e6a437fb3a4f3f0f60235717c9f7621408d Author: Uwe Seimet Date: Sun Dec 19 12:38:35 2021 +0100 Fixed typo commit cb1b498459b700556700575946264a3a8eabfb96 Author: Uwe Seimet Date: Sun Dec 19 12:37:13 2021 +0100 Interface comment update commit e2d4347ce6daa0a1c3de606aead8cadeb203881a Author: Uwe Seimet Date: Sun Dec 19 12:35:50 2021 +0100 Logging update commit cecb72df3ea9c1b27071d4b62017449709206ec9 Author: Uwe Seimet Date: Sun Dec 19 12:13:44 2021 +0100 Added operation commit bbf153ccd673004e371f5fb1f325ad2f3d95a97d Author: Uwe Seimet Date: Sun Dec 19 12:09:49 2021 +0100 Fixed typo commit 29fa5c2f962c6e775b82940682121c6d41ffb5fc Merge: 28a36fa ec31198 Author: Uwe Seimet Date: Sun Dec 19 12:07:34 2021 +0100 Merge branch 'develop' into feature_meta_data commit 28a36fa308d926fce4885f16a019604060ff1107 Author: Uwe Seimet Date: Sat Dec 18 15:51:02 2021 +0100 Description updates commit 73df9f136ca572ba160918acf85ecf06d0bd7d2c Author: Uwe Seimet Date: Sat Dec 18 14:37:58 2021 +0100 Comment update commit c3ea3c8b372284468c8302b82067454d17cd061c Author: Uwe Seimet Date: Sat Dec 18 14:34:48 2021 +0100 Renaming commit 6a84edd0fbab8253e47c024ae65529c1c5b246ef Author: Uwe Seimet Date: Sat Dec 18 14:22:31 2021 +0100 Comment update commit c0d6e66afe819bbcfeb5c606ba7cbc257b39dfec Author: Uwe Seimet Date: Sat Dec 18 14:20:20 2021 +0100 Code cleanup commit cc81b588eb6bea2014a9abec6d67cdbe849e76e0 Author: Uwe Seimet Date: Sat Dec 18 14:18:31 2021 +0100 Renaming commit c88628e12ad252420f29ebed0541a1c3c4ede231 Author: Uwe Seimet Date: Sat Dec 18 14:17:50 2021 +0100 Sort map by operation name commit b64001e8a4a6941a8f671420e61121f471f90010 Author: Uwe Seimet Date: Sat Dec 18 13:39:44 2021 +0100 Data type update commit 8177cd306222c8674fbcf889be634565bbd2337f Author: Uwe Seimet Date: Sat Dec 18 13:37:23 2021 +0100 Added cast commit b8599ba0886363d91399bba6fa4607fd7b3fd445 Author: Uwe Seimet Date: Sat Dec 18 13:35:40 2021 +0100 Added safeguard against unknown operations commit 6b14ba651135db152fe57c6fe469227f71f00969 Author: Uwe Seimet Date: Sat Dec 18 13:26:21 2021 +0100 Map operations by ordinal commit ee101f2c6b8dbf527f77c8e005f2ded9ebdf4436 Author: Uwe Seimet Date: Sat Dec 18 13:14:31 2021 +0100 Comment update commit 67c958ed371f35870e9acf91bd90446c46783264 Author: Uwe Seimet Date: Sat Dec 18 13:13:06 2021 +0100 Comment update commit d1a9c4074576e75300d990a346abd2357a536138 Author: Uwe Seimet Date: Sat Dec 18 13:04:58 2021 +0100 Default value update commit d9dbbc0bb3347832619c3e600405d4b3cf25d0da Author: Uwe Seimet Date: Sat Dec 18 12:47:36 2021 +0100 Squashed commit of the following: commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce Author: Uwe Seimet Date: Sat Dec 18 12:43:14 2021 +0100 The data type is implicit commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c Author: Uwe Seimet Date: Sat Dec 18 12:37:49 2021 +0100 Renaming commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089 Author: Uwe Seimet Date: Sat Dec 18 12:29:54 2021 +0100 Comment update commit 5f699aad2f835f72accdb445d1e59f094aeb108f Author: Uwe Seimet Date: Sat Dec 18 12:24:25 2021 +0100 Signature update commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e Author: Uwe Seimet Date: Sat Dec 18 12:22:45 2021 +0100 Signature update commit a8148ef802ca809e5a305d2caa69856c9033d932 Author: Uwe Seimet Date: Sat Dec 18 12:16:46 2021 +0100 Comment update commit ce685a92d4827e131d80d10ecd56e2b3baf173f8 Author: Uwe Seimet Date: Sat Dec 18 12:15:46 2021 +0100 Use map instead of list commit 454c0438f3589904f5dbe5253963dd200ea416dd Author: Uwe Seimet Date: Sat Dec 18 10:47:36 2021 +0100 Updated size check commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2 Author: Uwe Seimet Date: Sat Dec 18 01:23:43 2021 +0100 Initial improvements commit 5d6862b6b0fcd2f6b59779c7d47fdc99af748a28 Author: Uwe Seimet Date: Fri Dec 17 23:22:27 2021 +0100 Description upddate commit 69263b3e4b8c9443d6593db49b4bbb995d884382 Author: Uwe Seimet Date: Fri Dec 17 23:21:38 2021 +0100 Description update commit 49e14f7078ae419766326758a923bde69af8eb9d Author: Uwe Seimet Date: Fri Dec 17 23:19:08 2021 +0100 Removed redundant message field commit ff468aafa85a25c3f48a8bfdc1eb0a24b3fca63f Author: Uwe Seimet Date: Fri Dec 17 23:09:18 2021 +0100 Added support for default value commit 2da717a0a037653d9b182439271165eb1859ed8d Author: Uwe Seimet Date: Fri Dec 17 22:57:59 2021 +0100 For completeness sake added permitted boolean values commit 5d894d2e4f39b75e1672c430d5421df397d5ed10 Author: Uwe Seimet Date: Fri Dec 17 22:53:07 2021 +0100 Display permitted values commit acc7d3cba5e667f690f76d68e6d8aa373faf1db5 Author: Uwe Seimet Date: Fri Dec 17 20:37:03 2021 +0100 Comment update commit f846242aea70c723241eee7ed99943f54694e1e7 Author: Uwe Seimet Date: Fri Dec 17 20:35:07 2021 +0100 Code cleanup commit 5a9592f102a93bbe0acde908e9f0f7b9bebf1e41 Author: Uwe Seimet Date: Fri Dec 17 20:24:33 2021 +0100 Added convenience method commit 9d258d9979afe452ed58ef58c24b73b4ef2bfb05 Author: Uwe Seimet Date: Fri Dec 17 20:05:53 2021 +0100 Added convenience method commit 6c4103989baee3fcffeeb040b501cc6aae9b4b0d Author: Uwe Seimet Date: Fri Dec 17 19:45:20 2021 +0100 Comment update commit 7d543451f059cd12bed4a8a49bdfd1e8c0a7d706 Author: Uwe Seimet Date: Fri Dec 17 19:27:50 2021 +0100 Description updates commit f4b0e50e663e5736f4ed1ec176dea2b10cf9d006 Author: Uwe Seimet Date: Fri Dec 17 19:23:29 2021 +0100 Comment update commit 35dd3f6282cf3253b04e1eea1d25c5ad65247690 Author: Uwe Seimet Date: Fri Dec 17 19:21:12 2021 +0100 Type update commit 7a94c0e6e0641e1aaa62f892a3f70975165cbca0 Author: Uwe Seimet Date: Fri Dec 17 19:17:05 2021 +0100 Manpage update commit 4179110bac97268860a1b5bed32d18b0b944bda6 Author: Uwe Seimet Date: Fri Dec 17 19:13:42 2021 +0100 rasctl -s returns operation meta data commit eed83bb005b1f03df7f10c451a7cf2d872d42b0a Author: Uwe Seimet Date: Fri Dec 17 19:05:29 2021 +0100 Completed meta data commit 4a7528d9d320bbac4f77d29f293cb99da56561bb Author: Uwe Seimet Date: Fri Dec 17 18:39:18 2021 +0100 Sort operations commit d3af9a142ceb2dcfb3f0dc310925eff3bf62071b Author: Uwe Seimet Date: Fri Dec 17 18:29:22 2021 +0100 Support for localized descriptions commit b4ff4f52ab03683f76b6f23b057063ca67f1b9dd Author: Uwe Seimet Date: Fri Dec 17 17:53:11 2021 +0100 Interface update commit e8d9e97fe5c3e64fab57ccff8cfdb60fe24a849d Author: Uwe Seimet Date: Fri Dec 17 16:59:49 2021 +0100 Comment update commit 22753b15471166a34748113026b1e46b4c3b6888 Author: Uwe Seimet Date: Fri Dec 17 16:57:39 2021 +0100 Added messages commit b3a92924588513787e89908310d450306064e946 Merge: ea3bb83 94786ae Author: Uwe Seimet Date: Tue Dec 21 08:57:56 2021 +0100 Merge branch 'develop' into feature_folder_filter commit ea3bb8363a2a9a734abd2fc330066c52d5638b6d Author: Uwe Seimet Date: Tue Dec 21 08:53:30 2021 +0100 Squashed commit of the following: commit 94786aec54c589c080dcec3b18b388a17de64ae3 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Tue Dec 21 08:43:21 2021 +0100 Added support for operation meta data, code cleanup (#534) * Added messages * Comment update * Interface update * Support for localized descriptions * Sort operations * Completed meta data * rasctl -s returns operation meta data * Manpage update * Type update * Comment update * Description updates * Comment update * Added convenience method * Added convenience method * Code cleanup * Comment update * Display permitted values * For completeness sake added permitted boolean values * Added support for default value * Removed redundant message field * Description update * Description upddate * Squashed commit of the following: commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce Author: Uwe Seimet Date: Sat Dec 18 12:43:14 2021 +0100 The data type is implicit commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c Author: Uwe Seimet Date: Sat Dec 18 12:37:49 2021 +0100 Renaming commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089 Author: Uwe Seimet Date: Sat Dec 18 12:29:54 2021 +0100 Comment update commit 5f699aad2f835f72accdb445d1e59f094aeb108f Author: Uwe Seimet Date: Sat Dec 18 12:24:25 2021 +0100 Signature update commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e Author: Uwe Seimet Date: Sat Dec 18 12:22:45 2021 +0100 Signature update commit a8148ef802ca809e5a305d2caa69856c9033d932 Author: Uwe Seimet Date: Sat Dec 18 12:16:46 2021 +0100 Comment update commit ce685a92d4827e131d80d10ecd56e2b3baf173f8 Author: Uwe Seimet Date: Sat Dec 18 12:15:46 2021 +0100 Use map instead of list commit 454c0438f3589904f5dbe5253963dd200ea416dd Author: Uwe Seimet Date: Sat Dec 18 10:47:36 2021 +0100 Updated size check commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2 Author: Uwe Seimet Date: Sat Dec 18 01:23:43 2021 +0100 Initial improvements * Default value update * Comment update * Comment update * Map operations by ordinal * Added safeguard against unknown operations * Added cast * Data type update * Sort map by operation name * Renaming * Code cleanup * Comment update * Renaming * Comment update * Description updates * Fixed typo * Added operation * Logging update * Interface comment update * Fixed typo * Aded operation parameters * Updated handling of mandatory parameters * Updated assertion handling * Added missing condition * Removed duplicate cod3 * Code cleanup * Logging update * Removed duplicate code * Code cleanup * Squashed commit of the following: commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup * Shutdown functionality is only available if started with root permissions * Only restrict shutdown parameters, not everything if not root * Updated operation count check commit 693ade296756ee8e480e75663a873e4a35829034 Author: Daniel Markstedt Date: Mon Dec 20 12:04:23 2021 -0800 Bump Macproxy version to 21.12.2 (#550) commit 958fb95908f2d8cdf13c02d827f2d14f6011170e Author: akuker <34318535+akuker@users.noreply.github.com> Date: Mon Dec 20 12:50:14 2021 -0600 Adjust bus settle delay to match SCSI standard (#544) * Move the GCC v10 compiler flags into makefile instead of easyinstall.sh * #504 - Update the bus settle time to match the SCSI standard Co-authored-by: RaSCSI User commit 200bc7251f2395842df7c7be9b90f2b44940a9d4 Author: Daniel Markstedt Date: Mon Dec 20 06:20:22 2021 -0800 More helpful error message when IP does not resolve for OLED screen (#541) * More helpful error message * Remove confusing fallback IP * Tweak message commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup commit 94786aec54c589c080dcec3b18b388a17de64ae3 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Tue Dec 21 08:43:21 2021 +0100 Added support for operation meta data, code cleanup (#534) * Added messages * Comment update * Interface update * Support for localized descriptions * Sort operations * Completed meta data * rasctl -s returns operation meta data * Manpage update * Type update * Comment update * Description updates * Comment update * Added convenience method * Added convenience method * Code cleanup * Comment update * Display permitted values * For completeness sake added permitted boolean values * Added support for default value * Removed redundant message field * Description update * Description upddate * Squashed commit of the following: commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce Author: Uwe Seimet Date: Sat Dec 18 12:43:14 2021 +0100 The data type is implicit commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c Author: Uwe Seimet Date: Sat Dec 18 12:37:49 2021 +0100 Renaming commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089 Author: Uwe Seimet Date: Sat Dec 18 12:29:54 2021 +0100 Comment update commit 5f699aad2f835f72accdb445d1e59f094aeb108f Author: Uwe Seimet Date: Sat Dec 18 12:24:25 2021 +0100 Signature update commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e Author: Uwe Seimet Date: Sat Dec 18 12:22:45 2021 +0100 Signature update commit a8148ef802ca809e5a305d2caa69856c9033d932 Author: Uwe Seimet Date: Sat Dec 18 12:16:46 2021 +0100 Comment update commit ce685a92d4827e131d80d10ecd56e2b3baf173f8 Author: Uwe Seimet Date: Sat Dec 18 12:15:46 2021 +0100 Use map instead of list commit 454c0438f3589904f5dbe5253963dd200ea416dd Author: Uwe Seimet Date: Sat Dec 18 10:47:36 2021 +0100 Updated size check commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2 Author: Uwe Seimet Date: Sat Dec 18 01:23:43 2021 +0100 Initial improvements * Default value update * Comment update * Comment update * Map operations by ordinal * Added safeguard against unknown operations * Added cast * Data type update * Sort map by operation name * Renaming * Code cleanup * Comment update * Renaming * Comment update * Description updates * Fixed typo * Added operation * Logging update * Interface comment update * Fixed typo * Aded operation parameters * Updated handling of mandatory parameters * Updated assertion handling * Added missing condition * Removed duplicate cod3 * Code cleanup * Logging update * Removed duplicate code * Code cleanup * Squashed commit of the following: commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup * Shutdown functionality is only available if started with root permissions * Only restrict shutdown parameters, not everything if not root * Updated operation count check commit 693ade296756ee8e480e75663a873e4a35829034 Author: Daniel Markstedt Date: Mon Dec 20 12:04:23 2021 -0800 Bump Macproxy version to 21.12.2 (#550) commit 958fb95908f2d8cdf13c02d827f2d14f6011170e Author: akuker <34318535+akuker@users.noreply.github.com> Date: Mon Dec 20 12:50:14 2021 -0600 Adjust bus settle delay to match SCSI standard (#544) * Move the GCC v10 compiler flags into makefile instead of easyinstall.sh * #504 - Update the bus settle time to match the SCSI standard Co-authored-by: RaSCSI User commit 200bc7251f2395842df7c7be9b90f2b44940a9d4 Author: Daniel Markstedt Date: Mon Dec 20 06:20:22 2021 -0800 More helpful error message when IP does not resolve for OLED screen (#541) * More helpful error message * Remove confusing fallback IP * Tweak message commit f59eeb842ef5a71020bd1ae642eb9fe250963ea5 Author: Uwe Seimet Date: Mon Dec 20 10:25:28 2021 +0100 Squashed commit of the following: commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup commit 670356e0e29b4c03ddb5f02f0621043881766ad6 Author: Uwe Seimet Date: Sun Dec 19 20:26:03 2021 +0100 Code cleanup commit 4fc8f679758aef6d29a73850a7b8d15541b496e6 Author: Uwe Seimet Date: Sun Dec 19 20:21:10 2021 +0100 Manpage update commit 29603a327a8bdbe2241200ccef7df8a36415fcf4 Author: Uwe Seimet Date: Sun Dec 19 19:49:56 2021 +0100 Added optional folder name filter commit ec31198d83f5ff7400d74d7acf08c832998deb91 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sun Dec 19 11:54:10 2021 +0100 Optional authentication by access token (#529) * Added authentication by access token * No authentication is required for getting the rascsi version * Added comment * Interface description update * Manpage update * Added error code * Enum value update (backwards compatible) * Error code update * Error code update * Added CHECK_AUTHENTICATION * Comment update * VERSION_INFO also requires authentication * rasctl: Made token an optional parameter for -P * Fixed interface comment commit e32211ef737d1a435ee8ca1d7244b3609202b28f Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sun Dec 19 11:49:17 2021 +0100 Recursive image file scan and image file filter (#532) * Extracted code * Initial support for (optional) recursive image file listings * Manpage update * Added support for image file filter * Updated filtering * Made image scan depth configurable * Interface update * Squashed commit of the following: commit 6c98228726c26936c81b498d2837c7af7731be3c Author: Uwe Seimet Date: Mon Dec 20 22:45:24 2021 +0100 Fixed scan depth check commit 87e8b3be6a74d873efd982b027049ee0aebe6184 Author: Uwe Seimet Date: Mon Dec 20 20:46:36 2021 +0100 Added depth to image info commit 7c08fa6569e4c91132ff50f02a1c5d79935d78a3 Author: Uwe Seimet Date: Mon Dec 20 20:38:53 2021 +0100 Interface comment updates commit 29d919d30eeb0322ad0178e4a14190089c505062 Author: Uwe Seimet Date: Mon Dec 20 20:06:02 2021 +0100 Error message update commit fe76a1a577929f4f5b0517f859b58a611811b520 Author: Uwe Seimet Date: Mon Dec 20 19:56:36 2021 +0100 Renaming commit 412b53ddf185406cf8ce7b6eab54e2271a110aaf Merge: bf9d906 958fb95 Author: Uwe Seimet Date: Mon Dec 20 19:50:53 2021 +0100 Merge branch 'develop' into feature_file_operations_with_folders commit 958fb95908f2d8cdf13c02d827f2d14f6011170e Author: akuker <34318535+akuker@users.noreply.github.com> Date: Mon Dec 20 12:50:14 2021 -0600 Adjust bus settle delay to match SCSI standard (#544) * Move the GCC v10 compiler flags into makefile instead of easyinstall.sh * #504 - Update the bus settle time to match the SCSI standard Co-authored-by: RaSCSI User commit bf9d90664cfd6c5e85ec16a607dcf1de9067db7e Author: Uwe Seimet Date: Mon Dec 20 19:42:36 2021 +0100 Fixed warning commit 362a90f3dc2960bf9b272073bb1904a8879e4486 Author: Uwe Seimet Date: Mon Dec 20 19:37:32 2021 +0100 Updated error handling commit 66c380bd974fd5ada7b254d702d123ac775e768f Author: Uwe Seimet Date: Mon Dec 20 19:33:01 2021 +0100 Check image file nesting level commit c98a2b906929b6e10cc7a43d038c5a0671e8c6a1 Author: Uwe Seimet Date: Mon Dec 20 19:06:18 2021 +0100 Fixed typo commit a36dabc00216aa22ec2953d17b2293ad0c7bf7fc Author: Uwe Seimet Date: Mon Dec 20 19:03:18 2021 +0100 Code cleanup commit 46fc22f72aabe0e51d2519a540707369eb91d8fc Author: Uwe Seimet Date: Mon Dec 20 18:58:27 2021 +0100 Delete empty folders commit d55bf3e06f7d2ab9f64ffe89d8e383f9b4dcca5e Author: Uwe Seimet Date: Mon Dec 20 18:33:59 2021 +0100 Updated delete operation commit 5afce5f50fd113c3d925f8b81e42247d8bd1b789 Author: Uwe Seimet Date: Mon Dec 20 18:31:55 2021 +0100 Copy/rename/create commit b969d3990a5b21905e21ecb572e3ab1f19f52ccb Author: Uwe Seimet Date: Mon Dec 20 15:21:17 2021 +0100 Cleanup commit 200bc7251f2395842df7c7be9b90f2b44940a9d4 Author: Daniel Markstedt Date: Mon Dec 20 06:20:22 2021 -0800 More helpful error message when IP does not resolve for OLED screen (#541) * More helpful error message * Remove confusing fallback IP * Tweak message commit 6a6efa6bdd9974b4e0bb00b603914f824375a997 Author: Uwe Seimet Date: Mon Dec 20 12:58:29 2021 +0100 Cleanup commit 72ab669158d55f8008f4c80a882356cad42a4c53 Author: Uwe Seimet Date: Mon Dec 20 12:58:03 2021 +0100 Check for existing folder commit 6a9ac4d0dafbc4e385a7553d03e2dce21f88b7ae Author: Uwe Seimet Date: Mon Dec 20 12:52:26 2021 +0100 Code cleanup, initial support for creating nested file commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup commit ec31198d83f5ff7400d74d7acf08c832998deb91 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sun Dec 19 11:54:10 2021 +0100 Optional authentication by access token (#529) * Added authentication by access token * No authentication is required for getting the rascsi version * Added comment * Interface description update * Manpage update * Added error code * Enum value update (backwards compatible) * Error code update * Error code update * Added CHECK_AUTHENTICATION * Comment update * VERSION_INFO also requires authentication * rasctl: Made token an optional parameter for -P * Fixed interface comment commit e32211ef737d1a435ee8ca1d7244b3609202b28f Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Sun Dec 19 11:49:17 2021 +0100 Recursive image file scan and image file filter (#532) * Extracted code * Initial support for (optional) recursive image file listings * Manpage update * Added support for image file filter * Updated filtering * Made image scan depth configurable * Code cleanup * Resolved merged issues * Fixed merge issue * Comment update * Message update * Fixed typo * Logging update * Logging update * Logging update * Fixed merge issue * Set pattern param for SERVER_INFO * Added missing break * Updated error handling * Logging update * Error message update * Removed initial approach for localization in remote interface * Added command context * Initialize context * Initial localization support class * Localized authentication error * Comment update * Added TODO * Merge with develop * Only localize remote interface errors, but not log messages * Removed TODO * Use enum as localization key * Added consistency checks * Updated consitency checks * Fixed initial entries * Added fallback * Locales are always treated lower case * Support for string parameters * Added convenience method * Added localization support to rasctl * Error message update * Error handling update * Error handling update * Concatenate strings instead of using stream for error messages * Error message handling update * Error handling update * Comment update * Removed obsolete method * Logging update * Code cleanup * Added assertions * Code cleanup * Updated empty string handling * Code cleanup * Added localized messages * Added error messages * Added more error messages * Fixed typo * Translation update * Translation update * Uodated default locale handling * Updated locale handling * Manpage update * Removed debug code * Added translations * Added translations * Add Swedish localization * Swedish fix * Added -z option to rascsi * Manpage update Co-authored-by: Daniel Markstedt --- doc/rascsi.1 | 4 + doc/rascsi_man_page.txt | 22 ++- doc/rasctl.1 | 4 + doc/rasctl_man_page.txt | 5 +- src/raspberrypi/Makefile | 6 +- src/raspberrypi/command_context.h | 17 ++ src/raspberrypi/localizer.cpp | 130 ++++++++++++++ src/raspberrypi/localizer.h | 59 +++++++ src/raspberrypi/protobuf_util.cpp | 34 ++-- src/raspberrypi/protobuf_util.h | 10 +- src/raspberrypi/rascsi.cpp | 234 ++++++++++++------------- src/raspberrypi/rascsi_image.cpp | 120 ++++++------- src/raspberrypi/rascsi_image.h | 13 +- src/raspberrypi/rascsi_interface.proto | 3 +- src/raspberrypi/rascsi_response.cpp | 5 +- src/raspberrypi/rasctl.cpp | 19 +- src/raspberrypi/rasctl_commands.cpp | 8 +- src/raspberrypi/rasctl_commands.h | 3 +- 18 files changed, 475 insertions(+), 221 deletions(-) create mode 100644 src/raspberrypi/command_context.h create mode 100644 src/raspberrypi/localizer.cpp create mode 100644 src/raspberrypi/localizer.h diff --git a/doc/rascsi.1 b/doc/rascsi.1 index cc8a8304..37d767d9 100644 --- a/doc/rascsi.1 +++ b/doc/rascsi.1 @@ -13,6 +13,7 @@ rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins [\fB\-r\fR \fIRESERVED_IDS\fR] [\fB\-n\fR \fITYPE\fR] [\fB\-v\fR] +[\fB\-z\fR \fILOCALE\fR] [\fB\-IDn:[u]\fR \fIFILE\fR] [\fB\-HDn[:u]\fR \fIFILE\fR]... .SH DESCRIPTION @@ -77,6 +78,9 @@ The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, S .BR \-v\fI " " \fI Display the rascsi version. .TP +.BR \-z\fI " "\fILOCALE +Overrides the default locale for client-faces error messages. The client can override the locale. +.TP .BR \-ID\fIn[:u] " " \fIFILE n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0. .IP diff --git a/doc/rascsi_man_page.txt b/doc/rascsi_man_page.txt index f2acc911..1a384b32 100644 --- a/doc/rascsi_man_page.txt +++ b/doc/rascsi_man_page.txt @@ -8,8 +8,8 @@ NAME SYNOPSIS rascsi [-F[u00AE] FOLDER] [-L[u00AE] LOG_LEVEL] [-P[u00AE] ACCESS_TO‐ KEN_FILE] [-R SCAN_DEPTH] [-h] [-n VENDOR:PRODUCT:REVISION] [-p[u00AE] - PORT] [-r RESERVED_IDS] [-n TYPE] [-v] [-IDn:[u] FILE] [-HDn[:u] - FILE]... + PORT] [-r RESERVED_IDS] [-n TYPE] [-v] [-z LOCALE] [-IDn:[u] FILE] + [-HDn[:u] FILE]... DESCRIPTION rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins. @@ -99,18 +99,22 @@ OPTIONS -v Display the rascsi version. + -z LOCALE + Overrides the default locale for client-faces error messages. + The client can override the locale. + -IDn[:u] FILE - n is the SCSI ID number (0-7). u (0-31) is the optional LUN + n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0. - FILE is the name of the image file to use for the SCSI device. - For devices that do not support an image file (SCBR, SCDP) a + FILE is the name of the image file to use for the SCSI device. + For devices that do not support an image file (SCBR, SCDP) a dummy name must be provided. -HDn[:u] FILE - n is the SASI ID number (0-15). The effective SASI ID is calcu‐ - lated as n/2, the effective SASI LUN is calculated is the re‐ - mainder of n/2. Alternatively the n:u syntax can be used, where + n is the SASI ID number (0-15). The effective SASI ID is calcu‐ + lated as n/2, the effective SASI LUN is calculated is the re‐ + mainder of n/2. Alternatively the n:u syntax can be used, where ns is the SASI ID (0-7) and u the LUN (0-1). FILE is the name of the image file to use for the SASI device. @@ -127,7 +131,7 @@ EXAMPLES rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de‐ - vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter + vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter as ID 6: rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME diff --git a/doc/rasctl.1 b/doc/rasctl.1 index 7b9d41bb..eb7e50f6 100644 --- a/doc/rasctl.1 +++ b/doc/rasctl.1 @@ -32,6 +32,7 @@ rasctl \- Sends management commands to the rascsi process [\fB\-t\fR \fITYPE\fR] [\fB\-u\fR \fIUNIT\fR] [\fB\-x\fR \fICURRENT_NAME:NEW_NAME\fR] +[\fB\-z\fR \fILOCALE\fR] .SH DESCRIPTION .B rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices. @@ -116,6 +117,9 @@ Delete an image file in the default image folder. .BR \-x\fI " "\fICURRENT_NAME:NEW_NAME Copy an image file in the default image folder. .TP +.BR \-z\fI " "\fILOCALE +Overrides the default locale for client-facing error messages. +.TP .BR \-i\fI " " \fIID ID is the SCSI ID that you want to control. (0-7) .TP diff --git a/doc/rasctl_man_page.txt b/doc/rasctl_man_page.txt index 956c760e..f109a0f5 100644 --- a/doc/rasctl_man_page.txt +++ b/doc/rasctl_man_page.txt @@ -10,7 +10,7 @@ SYNOPSIS -X | [-C FILENAME:FILESIZE] [-E FILENAME] [-F IMAGE_FOLDER] [-R CUR‐ RENT_NAME:NEW_NAME] [-c CMD] [-f FILE|PARAM] [-g LOG_LEVEL] [-h HOST] [-i ID [-n NAME] [-p PORT] [-r RESERVED_IDS] [-t TYPE] [-u UNIT] [-x - CURRENT_NAME:NEW_NAME] + CURRENT_NAME:NEW_NAME] [-z LOCALE] DESCRIPTION rasctl Sends commands to the rascsi process to make configuration ad‐ @@ -90,6 +90,9 @@ OPTIONS -x CURRENT_NAME:NEW_NAME Copy an image file in the default image folder. + -z LOCALE + Overrides the default locale for client-facing error messages. + -i ID ID is the SCSI ID that you want to control. (0-7) -c CMD Command is the operation being requested. Options are: diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index bd0df3d3..81ecefdc 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -95,7 +95,8 @@ SRC_RASCSI = \ rascsi_image.cpp \ rascsi_response.cpp \ rasutil.cpp \ - protobuf_util.cpp + protobuf_util.cpp \ + localizer.cpp SRC_RASCSI += $(shell find ./controllers -name '*.cpp') SRC_RASCSI += $(shell find ./devices -name '*.cpp') SRC_RASCSI += $(SRC_PROTOBUF) @@ -114,7 +115,8 @@ SRC_RASCTL = \ rasctl_display.cpp \ rascsi_version.cpp \ rasutil.cpp \ - protobuf_util.cpp + protobuf_util.cpp \ + localizer.cpp SRC_RASCTL += $(SRC_PROTOBUF) SRC_RASDUMP = \ diff --git a/src/raspberrypi/command_context.h b/src/raspberrypi/command_context.h new file mode 100644 index 00000000..37ae76ba --- /dev/null +++ b/src/raspberrypi/command_context.h @@ -0,0 +1,17 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Copyright (C) 2021 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#pragma once + +#include + +struct CommandContext { + int fd; + std::string locale; +}; diff --git a/src/raspberrypi/localizer.cpp b/src/raspberrypi/localizer.cpp new file mode 100644 index 00000000..36b4393f --- /dev/null +++ b/src/raspberrypi/localizer.cpp @@ -0,0 +1,130 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Copyright (C) 2021 Uwe Seimet +// +//--------------------------------------------------------------------------- + +#include "localizer.h" +#include +#include +#include +#include +#include + +using namespace std; + +Localizer::Localizer() +{ + // Supported locales, always lower case + supported_languages = { "en", "de", "sv" }; + + // Positional string arguments are %1, %2, %3 + Add(ERROR_AUTHENTICATION, "en", "Authentication failed"); + Add(ERROR_AUTHENTICATION, "de", "Authentifizierung fehlgeschlagen"); + Add(ERROR_AUTHENTICATION, "sv", "Autentisering misslyckades"); + Add(ERROR_OPERATION, "en", "Unknown operation"); + Add(ERROR_OPERATION, "de", "Unbekannte Operation"); + Add(ERROR_OPERATION, "sv", "Okänd operation"); + Add(ERROR_LOG_LEVEL, "en", "Invalid log level %1"); + Add(ERROR_LOG_LEVEL, "de", "Ungültiger Log-Level %1"); + Add(ERROR_LOG_LEVEL, "sv", "Ogiltig loggnivå %1"); + Add(ERROR_MISSING_DEVICE_ID, "en", "Missing device ID"); + Add(ERROR_MISSING_DEVICE_ID, "de", "Fehlende Geräte-ID"); + Add(ERROR_MISSING_DEVICE_ID, "sv", "Enhetens ID saknas"); + Add(ERROR_MISSING_FILENAME, "en", "Missing filename"); + Add(ERROR_MISSING_FILENAME, "de", "Fehlender Dateiname"); + Add(ERROR_MISSING_FILENAME, "sv", "Filnamn saknas"); + Add(ERROR_IMAGE_IN_USE, "en", "Image file '%1' is already being used by ID %2, unit %3"); + Add(ERROR_IMAGE_IN_USE, "de", "Image-Datei '%1' wird bereits von ID %2, Einheit %3 benutzt"); + Add(ERROR_IMAGE_IN_USE, "sv", "Skivbildfilen '%1' används redan av ID %2, LUN %3"); + Add(ERROR_RESERVED_ID, "en", "Device ID %1 is reserved"); + Add(ERROR_RESERVED_ID, "de", "Geräte-ID %1 ist reserviert"); + Add(ERROR_RESERVED_ID, "sv", "Enhets-ID %1 är reserverat"); + Add(ERROR_NON_EXISTING_DEVICE, "en", "Command for non-existing ID %1"); + Add(ERROR_NON_EXISTING_DEVICE, "de", "Kommando für nicht existente ID %1"); + Add(ERROR_NON_EXISTING_DEVICE, "sv", "Kommando för avsaknat ID %1"); + Add(ERROR_NON_EXISTING_UNIT, "en", "Command for non-existing ID %1, unit %2"); + Add(ERROR_NON_EXISTING_UNIT, "de", "Kommando für nicht existente ID %1, Einheit %2"); + Add(ERROR_NON_EXISTING_UNIT, "sv", "Kommando för avsaknat ID %1, LUN %2"); + Add(ERROR_UNKNOWN_DEVICE_TYPE, "en", "Unknown device type %1"); + Add(ERROR_UNKNOWN_DEVICE_TYPE, "de", "Unbekannter Gerätetyp %1"); + Add(ERROR_UNKNOWN_DEVICE_TYPE, "sv", "Obekant enhetstyp: %1"); + Add(ERROR_MISSING_DEVICE_TYPE, "en", "Device type required for unknown extension of file '%1'"); + Add(ERROR_MISSING_DEVICE_TYPE, "de", "Gerätetyp erforderlich für unbekannte Extension der Datei '%1'"); + Add(ERROR_MISSING_DEVICE_TYPE, "sv", "Man måste ange enhetstyp för obekant filändelse '%1'"); + Add(ERROR_DUPLICATE_ID, "en", "Duplicate ID %1, unit %2"); + Add(ERROR_DUPLICATE_ID, "de", "Doppelte ID %1, Einheit %2"); + Add(ERROR_DUPLICATE_ID, "sv", "Duplikat ID %1, LUN %2"); + Add(ERROR_SASI_SCSI, "en", "SASI and SCSI can't be used at the same time"); + Add(ERROR_SASI_SCSI, "de", "SASI und SCSI können nicht gleichzeitig verwendet werden"); + Add(ERROR_SASI_SCSI, "sv", "SASI och SCSI kan ej användas samtidigt"); + Add(ERROR_EJECT_REQUIRED, "en", "Existing medium must first be ejected"); + Add(ERROR_EJECT_REQUIRED, "de", "Das vorhandene Medium muss erst ausgeworfen werden"); + Add(ERROR_EJECT_REQUIRED, "sv", "Nuvarande skiva måste utmatas först"); + Add(ERROR_DEVICE_NAME_UPDATE, "en", "Once set the device name cannot be changed anymore"); + Add(ERROR_DEVICE_NAME_UPDATE, "de", "Ein bereits gesetzter Gerätename kann nicht mehr geändert werden"); + Add(ERROR_DEVICE_NAME_UPDATE, "sv", "Enhetsnamn kan ej ändras efter att ha fastställts en gång"); + Add(ERROR_SHUTDOWN_MODE_MISSING, "en", "Missing shutdown mode"); + Add(ERROR_SHUTDOWN_MODE_MISSING, "de", "Fehlender Shutdown-Modus"); + Add(ERROR_SHUTDOWN_MODE_MISSING, "sv", "Avstängningsläge saknas"); + Add(ERROR_SHUTDOWN_MODE_INVALID, "en", "Invalid shutdown mode '%1'"); + Add(ERROR_SHUTDOWN_MODE_INVALID, "de", "Ungültiger Shutdown-Modus '%1'"); + Add(ERROR_SHUTDOWN_MODE_INVALID, "sv", "Ogiltigt avstängsningsläge: '%1'"); + Add(ERROR_SHUTDOWN_PERMISSION, "en", "Missing root permission for shutdown or reboot"); + Add(ERROR_SHUTDOWN_PERMISSION, "de", "Fehlende Root-Berechtigung für Shutdown oder Neustart"); + Add(ERROR_SHUTDOWN_PERMISSION, "sv", "Root-rättigheter saknas för att kunna stänga av eller starta om systemet"); + Add(ERROR_FILE_OPEN, "en", "Invalid or non-existing file '%1': %2"); + Add(ERROR_FILE_OPEN, "de", "Ungültige oder fehlende Datei '%1': %2"); + Add(ERROR_FILE_OPEN, "sv", "Ogiltig eller saknad fil '%1': %2"); + Add(ERROR_BLOCK_SIZE, "en", "Invalid block size %1 bytes"); + Add(ERROR_BLOCK_SIZE, "de", "Ungültige Blockgröße %1 Bytes"); + Add(ERROR_BLOCK_SIZE, "sv", "Ogiltig blockstorlek: %1 byte"); + Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "en", "Block size for device type %1 is not configurable"); + Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "de", "Blockgröße für Gerätetyp %1 ist nicht konfigurierbar"); + Add(ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, "sv", "Enhetstypen %1 kan inte använda andra blockstorlekar"); +} + +void Localizer::Add(LocalizationKey key, const string& locale, const string& value) +{ + // Safeguards against empty messages, duplicate entries and unsupported locales + assert(locale.size()); + assert(value.size()); + assert(supported_languages.find(locale) != supported_languages.end()); + assert(localized_messages[locale][key].empty()); + + localized_messages[locale][key] = value; +} + +string Localizer::Localize(LocalizationKey key, const string& locale, const string& arg1, const string& arg2, + const string &arg3) +{ + string locale_lower = locale; + transform(locale_lower.begin(), locale_lower.end(), locale_lower.begin(), ::tolower); + + map messages = localized_messages[locale_lower]; + if (messages.empty()) { + // Try to fall back to country-indepedent locale (e.g. "en" instead of "en_US") + if (locale_lower.length() > 2) { + messages = localized_messages[locale_lower.substr(0, 2)]; + } + if (messages.empty()) { + messages = localized_messages["en"]; + } + } + + assert(!messages.empty()); + + string message = messages[key]; + if (messages.empty()) { + return "Missing localization for enum value " + to_string(key); + } + + message = regex_replace(message, regex("%1"), arg1); + message = regex_replace(message, regex("%2"), arg2); + message = regex_replace(message, regex("%3"), arg3); + + return message; +} diff --git a/src/raspberrypi/localizer.h b/src/raspberrypi/localizer.h new file mode 100644 index 00000000..e59faf84 --- /dev/null +++ b/src/raspberrypi/localizer.h @@ -0,0 +1,59 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Copyright (C) 2021 Uwe Seimet +// +// Message localization support. Currently only for messages with up to 3 string parameters. +// +//--------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +using namespace std; + +enum LocalizationKey { + ERROR_AUTHENTICATION, + ERROR_OPERATION, + ERROR_LOG_LEVEL, + ERROR_MISSING_DEVICE_ID, + ERROR_MISSING_FILENAME, + ERROR_IMAGE_IN_USE, + ERROR_RESERVED_ID, + ERROR_NON_EXISTING_DEVICE, + ERROR_NON_EXISTING_UNIT, + ERROR_UNKNOWN_DEVICE_TYPE, + ERROR_MISSING_DEVICE_TYPE, + ERROR_DUPLICATE_ID, + ERROR_SASI_SCSI, + ERROR_EJECT_REQUIRED, + ERROR_DEVICE_NAME_UPDATE, + ERROR_SHUTDOWN_MODE_MISSING, + ERROR_SHUTDOWN_MODE_INVALID, + ERROR_SHUTDOWN_PERMISSION, + ERROR_FILE_OPEN, + ERROR_BLOCK_SIZE, + ERROR_BLOCK_SIZE_NOT_CONFIGURABLE +}; + +class Localizer +{ +public: + + Localizer(); + ~Localizer() {}; + + string Localize(LocalizationKey, const string&, const string& = "", const string& = "", const string& = ""); + +private: + + void Add(LocalizationKey, const string&, const string&); + map> localized_messages; + + set supported_languages; +}; diff --git a/src/raspberrypi/protobuf_util.cpp b/src/raspberrypi/protobuf_util.cpp index df672579..bc9239d1 100644 --- a/src/raspberrypi/protobuf_util.cpp +++ b/src/raspberrypi/protobuf_util.cpp @@ -11,6 +11,7 @@ #include "os.h" #include "log.h" #include "rascsi_interface.pb.h" +#include "localizer.h" #include "exceptions.h" #include "protobuf_util.h" @@ -19,6 +20,8 @@ using namespace rascsi_interface; #define FPRT(fp, ...) fprintf(fp, __VA_ARGS__ ) +Localizer localizer; + const string protobuf_util::GetParam(const PbCommand& command, const string& key) { auto map = command.params(); @@ -119,14 +122,30 @@ int protobuf_util::ReadNBytes(int fd, uint8_t *buf, int n) return offset; } - -bool protobuf_util::ReturnStatus(int fd, bool status, const string msg, const PbErrorCode error_code) +bool protobuf_util::ReturnLocalizedError(const CommandContext& context, const LocalizationKey key, + const string& arg1, const string& arg2, const string& arg3) { - if (!status && !msg.empty()) { + return ReturnLocalizedError(context, key, NO_ERROR_CODE, arg1, arg2, arg3); +} + +bool protobuf_util::ReturnLocalizedError(const CommandContext& context, const LocalizationKey key, + const PbErrorCode error_code, const string& arg1, const string& arg2, const string& arg3) +{ + // For the logfile always use English + LOGERROR("%s", localizer.Localize(key, "en", arg1, arg2, arg3).c_str()); + + return ReturnStatus(context, false, localizer.Localize(key, context.locale, arg1, arg2, arg3), error_code, false); +} + +bool protobuf_util::ReturnStatus(const CommandContext& context, bool status, const string& msg, + const PbErrorCode error_code, bool log) +{ + // Do not log twice if logging has already been done in the localized error handling above + if (log && !status && !msg.empty()) { LOGERROR("%s", msg.c_str()); } - if (fd == -1) { + if (context.fd == -1) { if (!msg.empty()) { if (status) { FPRT(stderr, "Error: "); @@ -144,13 +163,8 @@ bool protobuf_util::ReturnStatus(int fd, bool status, const string msg, const Pb result.set_status(status); result.set_error_code(error_code); result.set_msg(msg); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); } return status; } - -bool protobuf_util::ReturnStatus(int fd, bool status, const ostringstream& msg) -{ - return ReturnStatus(fd, status, msg.str()); -} diff --git a/src/raspberrypi/protobuf_util.h b/src/raspberrypi/protobuf_util.h index 9106d3e2..7390bbdc 100644 --- a/src/raspberrypi/protobuf_util.h +++ b/src/raspberrypi/protobuf_util.h @@ -13,6 +13,8 @@ #include "google/protobuf/message.h" #include "rascsi_interface.pb.h" +#include "command_context.h" +#include "localizer.h" #include #include @@ -29,6 +31,10 @@ namespace protobuf_util void SerializeMessage(int, const google::protobuf::Message&); void DeserializeMessage(int, google::protobuf::Message&); int ReadNBytes(int, uint8_t *, int); - bool ReturnStatus(int, bool = true, const string = "", const PbErrorCode error_code = PbErrorCode::NO_ERROR_CODE); - bool ReturnStatus(int, bool, const ostringstream&); + bool ReturnLocalizedError(const CommandContext&, const LocalizationKey, const string& = "", const string& = "", + const string& = ""); + bool ReturnLocalizedError(const CommandContext&, const LocalizationKey, const PbErrorCode, const string& = "", + const string& = "", const string& = ""); + bool ReturnStatus(const CommandContext&, bool = true, const string& = "", + const PbErrorCode = PbErrorCode::NO_ERROR_CODE, bool = true); } diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index d022da02..da90e030 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -442,10 +442,7 @@ string ValidateLunSetup(const PbCommand& command, const vector& existi } if (!is_consecutive) { - ostringstream error; - error << "LUNs for device ID " << id << " are not consecutive"; - - return error.str(); + return "LUNs for device ID " + to_string(id) + " are not consecutive"; } } @@ -557,16 +554,14 @@ void DetachAll() FileSupport::UnreserveAll(); } -bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dryRun) +bool Attach(const CommandContext& context, const PbDeviceDefinition& pb_device, Device *map[], bool dryRun) { const int id = pb_device.id(); const int unit = pb_device.unit(); const PbDeviceType type = pb_device.type(); - ostringstream error; if (map[id * UnitNum + unit]) { - error << "Duplicate ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_DUPLICATE_ID, to_string(id), to_string(unit)); } string filename = GetParam(pb_device, "file"); @@ -575,10 +570,10 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry Device *device = device_factory.CreateDevice(type, filename); if (!device) { if (type == UNDEFINED) { - return ReturnStatus(fd, false, "Device type required for unknown extension of file '" + filename + "'"); + return ReturnLocalizedError(context, ERROR_MISSING_DEVICE_TYPE, filename); } else { - return ReturnStatus(fd, false, "Unknown device type " + PbDeviceType_Name(type)); + return ReturnLocalizedError(context, ERROR_UNKNOWN_DEVICE_TYPE, PbDeviceType_Name(type)); } } @@ -586,6 +581,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry if (unit >= supported_luns) { delete device; + ostringstream error; error << "Invalid unit " << unit << " for device type " << PbDeviceType_Name(type); if (supported_luns == 1) { error << " (0)"; @@ -593,7 +589,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry else { error << " (0-" << (supported_luns -1) << ")"; } - return ReturnStatus(fd, false, error.str()); + return ReturnStatus(context, false, error.str()); } // If no filename was provided the medium is considered removed @@ -620,7 +616,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry } } catch(const illegal_argument_exception& e) { - return ReturnStatus(fd, false, e.getmsg()); + return ReturnStatus(context, false, e.getmsg()); } if (pb_device.block_size()) { @@ -629,14 +625,13 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry if (!disk->SetConfiguredSectorSize(pb_device.block_size())) { delete device; - error << "Invalid block size " << pb_device.block_size() << " bytes"; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_BLOCK_SIZE, to_string(pb_device.block_size())); } } else { delete device; - return ReturnStatus(fd, false, "Block size is not configurable for device type " + PbDeviceType_Name(type)); + return ReturnLocalizedError(context, ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, PbDeviceType_Name(type)); } } @@ -644,7 +639,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry if (file_support && !device->IsRemovable() && filename.empty()) { delete device; - return ReturnStatus(fd, false, "Device type " + PbDeviceType_Name(type) + " requires a filename"); + return ReturnStatus(context, false, "Device type " + PbDeviceType_Name(type) + " requires a filename"); } Filepath filepath; @@ -657,8 +652,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { delete device; - error << "Image file '" << filename << "' is already used by ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } try { @@ -672,8 +666,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { delete device; - error << "Image file '" << filename << "' is already used by ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } file_support->Open(filepath); @@ -682,7 +675,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry catch(const io_exception& e) { delete device; - return ReturnStatus(fd, false, "Tried to open an invalid or non-existing file '" + initial_filename + "': " + e.getmsg()); + return ReturnLocalizedError(context, ERROR_FILE_OPEN, initial_filename, e.getmsg()); } file_support->ReserveFile(filepath, device->GetId(), device->GetLun()); @@ -703,11 +696,10 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry std::map params = { pb_device.params().begin(), pb_device.params().end() }; if (!device->Init(params)) { - error << "Initialization of " << device->GetType() << " device, ID " << id << ", unit " << unit << " failed"; - delete device; - return ReturnStatus(fd, false, error); + return ReturnStatus(context, false, "Initialization of " + device->GetType() + " device, ID " +to_string(id) + + ", unit " +to_string(unit) + " failed"); } // Replace with the newly created unit @@ -729,10 +721,10 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry return true; } - return ReturnStatus(fd, false, "SASI and SCSI can't be mixed"); + return ReturnLocalizedError(context, ERROR_SASI_SCSI); } -bool Detach(int fd, Device *device, Device *map[], bool dryRun) +bool Detach(const CommandContext& context, Device *device, Device *map[], bool dryRun) { if (!dryRun) { for (auto const& d : devices) { @@ -756,19 +748,19 @@ bool Detach(int fd, Device *device, Device *map[], bool dryRun) return true; } -bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dryRun) +bool Insert(const CommandContext& context, const PbDeviceDefinition& pb_device, Device *device, bool dryRun) { if (!device->IsRemoved()) { - return ReturnStatus(fd, false, "Existing medium must first be ejected"); + return ReturnLocalizedError(context, ERROR_EJECT_REQUIRED); } if (!pb_device.vendor().empty() || !pb_device.product().empty() || !pb_device.revision().empty()) { - return ReturnStatus(fd, false, "Once set the device name cannot be changed anymore"); + return ReturnLocalizedError(context, ERROR_DEVICE_NAME_UPDATE); } string filename = GetParam(pb_device, "file"); if (filename.empty()) { - return ReturnStatus(fd, false, "Missing filename for " + PbOperation_Name(INSERT)); + return ReturnLocalizedError(context, ERROR_MISSING_FILENAME); } if (dryRun) { @@ -782,13 +774,11 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr Disk *disk = dynamic_cast(device); if (disk && disk->IsSectorSizeConfigurable()) { if (!disk->SetConfiguredSectorSize(pb_device.block_size())) { - ostringstream error; - error << "Invalid block size " << pb_device.block_size() << " bytes"; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_BLOCK_SIZE, to_string(pb_device.block_size())); } } else { - return ReturnStatus(fd, false, "Block size is not configurable for device type " + device->GetType()); + return ReturnLocalizedError(context, ERROR_BLOCK_SIZE_NOT_CONFIGURABLE, device->GetType()); } } @@ -799,9 +789,7 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr string initial_filename = filepath.GetPath(); if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { - ostringstream error; - error << "Image file '" << filename << "' is already used by ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } FileSupport *file_support = dynamic_cast(device); @@ -814,16 +802,14 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr filepath.SetPath((rascsi_image.GetDefaultImageFolder() + "/" + filename).c_str()); if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { - ostringstream error; - error << "Image file '" << filename << "' is already used by ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_IMAGE_IN_USE, filename, to_string(id), to_string(unit)); } file_support->Open(filepath); } } catch(const io_exception& e) { - return ReturnStatus(fd, false, "Tried to open an invalid or non-existing file '" + initial_filename + "': " + e.getmsg()); + return ReturnLocalizedError(context, ERROR_FILE_OPEN, initial_filename, e.getmsg()); } file_support->ReserveFile(filepath, device->GetId(), device->GetLun()); @@ -850,7 +836,7 @@ void TerminationHandler(int signum) // //--------------------------------------------------------------------------- -bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& command, bool dryRun) +bool ProcessCmd(const CommandContext& context, const PbDeviceDefinition& pb_device, const PbCommand& command, bool dryRun) { ostringstream error; @@ -896,20 +882,20 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& co LOGINFO("%s", s.str().c_str()); // Check the Controller Number - if (id < 0 || id >= CtrlMax) { - error << "Invalid device ID " << id << " (0-" << CtrlMax - 1 << ")"; - return ReturnStatus(fd, false, error); + if (id < 0) { + return ReturnLocalizedError(context, ERROR_MISSING_DEVICE_ID); + } + if (id >= CtrlMax) { + return ReturnStatus(context, false, "Invalid device ID " + to_string(id) + " (0-" + to_string(CtrlMax - 1) + ")"); } if (operation == ATTACH && reserved_ids.find(id) != reserved_ids.end()) { - error << "Device ID " << id << " is reserved"; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_RESERVED_ID, to_string(id)); } // Check the Unit Number if (unit < 0 || unit >= UnitNum) { - error << "Invalid unit " << unit << " (0-" << UnitNum - 1 << ")"; - return ReturnStatus(fd, false, error); + return ReturnStatus(context, false, "Invalid unit " + to_string(unit) + " (0-" + to_string(UnitNum - 1) + ")"); } // Copy the devices @@ -919,39 +905,37 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& co } if (operation == ATTACH) { - return Attach(fd, pb_device, map, dryRun); + return Attach(context, pb_device, map, dryRun); } // Does the controller exist? if (!dryRun && !controllers[id]) { - error << "Received a command for non-existing ID " << id; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_NON_EXISTING_DEVICE, to_string(id)); } // Does the unit exist? Device *device = devices[id * UnitNum + unit]; if (!device) { - error << "Received a command for a non-existing device or unit, ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, error); + return ReturnLocalizedError(context, ERROR_NON_EXISTING_UNIT, to_string(id), to_string(unit)); } if (operation == DETACH) { - return Detach(fd, device, map, dryRun); + return Detach(context, device, map, dryRun); } if ((operation == START || operation == STOP) && !device->IsStoppable()) { - return ReturnStatus(fd, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't stoppable)"); + return ReturnStatus(context, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't stoppable)"); } if ((operation == INSERT || operation == EJECT) && !device->IsRemovable()) { - return ReturnStatus(fd, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't removable)"); + return ReturnStatus(context, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't removable)"); } if ((operation == PROTECT || operation == UNPROTECT) && !device->IsProtectable()) { - return ReturnStatus(fd, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't protectable)"); + return ReturnStatus(context, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't protectable)"); } if ((operation == PROTECT || operation == UNPROTECT) && !device->IsReady()) { - return ReturnStatus(fd, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't ready)"); + return ReturnStatus(context, false, PbOperation_Name(operation) + " operation denied (" + device->GetType() + " isn't ready)"); } switch (operation) { @@ -975,7 +959,7 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& co break; case INSERT: - return Insert(fd, pb_device, device, dryRun); + return Insert(context, pb_device, device, dryRun); case EJECT: if (!dryRun) { @@ -1018,44 +1002,44 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& co break; default: - return ReturnStatus(fd, false, "Unknown operation"); + return ReturnLocalizedError(context, ERROR_OPERATION); } return true; } -bool ProcessCmd(const int fd, const PbCommand& command) +bool ProcessCmd(const CommandContext& context, const PbCommand& command) { switch (command.operation()) { case DETACH_ALL: DetachAll(); - return ReturnStatus(fd); + return ReturnStatus(context); case RESERVE_IDS: { const string ids = GetParam(command, "ids"); string error = SetReservedIds(ids); if (!error.empty()) { - return ReturnStatus(fd, false, error); + return ReturnStatus(context, false, error); } - return ReturnStatus(fd); + return ReturnStatus(context); } case CREATE_IMAGE: - return rascsi_image.CreateImage(fd, command); + return rascsi_image.CreateImage(context, command); case DELETE_IMAGE: - return rascsi_image.DeleteImage(fd, command); + return rascsi_image.DeleteImage(context, command); case RENAME_IMAGE: - return rascsi_image.RenameImage(fd, command); + return rascsi_image.RenameImage(context, command); case COPY_IMAGE: - return rascsi_image.CopyImage(fd, command); + return rascsi_image.CopyImage(context, command); case PROTECT_IMAGE: case UNPROTECT_IMAGE: - return rascsi_image.SetImagePermissions(fd, command); + return rascsi_image.SetImagePermissions(context, command); default: // This is a device-specific command handled below @@ -1065,7 +1049,7 @@ bool ProcessCmd(const int fd, const PbCommand& command) // Remember the list of reserved files, than run the dry run const auto reserved_files = FileSupport::GetReservedFiles(); for (const auto& device : command.devices()) { - if (!ProcessCmd(fd, device, command, true)) { + if (!ProcessCmd(context, device, command, true)) { // Dry run failed, restore the file list FileSupport::SetReservedFiles(reserved_files); return false; @@ -1077,26 +1061,26 @@ bool ProcessCmd(const int fd, const PbCommand& command) string result = ValidateLunSetup(command, devices); if (!result.empty()) { - return ReturnStatus(fd, false, result); + return ReturnStatus(context, false, result); } for (const auto& device : command.devices()) { - if (!ProcessCmd(fd, device, command, false)) { + if (!ProcessCmd(context, device, command, false)) { return false; } } // ATTACH and DETACH return the device list - if (fd != -1 && (command.operation() == ATTACH || command.operation() == DETACH)) { + if (context.fd != -1 && (command.operation() == ATTACH || command.operation() == DETACH)) { // A new command with an empty device list is required here in order to return data for all devices PbCommand command; PbResult result; rascsi_response.GetDevicesInfo(result, command, devices, UnitNum); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); return true; } - return ReturnStatus(fd); + return ReturnStatus(context); } bool ProcessId(const string id_spec, PbDeviceType type, int& id, int& unit) @@ -1130,9 +1114,9 @@ bool ProcessId(const string id_spec, PbDeviceType type, int& id, int& unit) return true; } -void ShutDown(int fd, const string& mode) { +void ShutDown(const CommandContext& context, const string& mode) { if (mode.empty()) { - ReturnStatus(fd, false, "Can't shut down: Missing shutdown mode"); + ReturnLocalizedError(context, ERROR_SHUTDOWN_MODE_MISSING); return; } @@ -1142,21 +1126,21 @@ void ShutDown(int fd, const string& mode) { if (mode == "rascsi") { LOGINFO("RaSCSI shutdown requested"); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); TerminationHandler(0); } // The root user has UID 0 if (getuid()) { - ReturnStatus(fd, false, "Can't shut down or reboot system: Missing root permissions"); + ReturnLocalizedError(context, ERROR_SHUTDOWN_PERMISSION); return; } if (mode == "system") { LOGINFO("System shutdown requested"); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); DetachAll(); @@ -1167,7 +1151,7 @@ void ShutDown(int fd, const string& mode) { else if (mode == "reboot") { LOGINFO("System reboot requested"); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); DetachAll(); @@ -1176,7 +1160,7 @@ void ShutDown(int fd, const string& mode) { } } else { - ReturnStatus(fd, false, "Invalid shutdown mode '" + mode + "'hi"); + ReturnLocalizedError(context, ERROR_SHUTDOWN_MODE_INVALID); } } @@ -1195,9 +1179,14 @@ bool ParseArgument(int argc, char* argv[], int& port) string name; string log_level; + string locale = setlocale(LC_MESSAGES, ""); + if (locale == "C") { + locale = "en"; + } + opterr = 1; int opt; - while ((opt = getopt(argc, argv, "-IiHhb:d:n:p:r:t:D:F:L:P:R:")) != -1) { + while ((opt = getopt(argc, argv, "-IiHhb:d:n:p:r:t:z:D:F:L:P:R:")) != -1) { switch (opt) { // The three options below are kind of a compound option with two letters case 'i': @@ -1229,6 +1218,10 @@ bool ParseArgument(int argc, char* argv[], int& port) continue; } + case 'z': + locale = optarg; + continue; + case 'F': { string result = rascsi_image.SetDefaultImageFolder(optarg); if (!result.empty()) { @@ -1337,7 +1330,10 @@ bool ParseArgument(int argc, char* argv[], int& port) // Attach all specified devices command.set_operation(ATTACH); - if (!ProcessCmd(-1, command)) { + CommandContext context; + context.fd = -1; + context.locale = locale; + if (!ProcessCmd(context, command)) { return false; } @@ -1397,21 +1393,22 @@ static void *MonThread(void *param) listen(monsocket, 1); while (true) { - int fd = -1; + CommandContext context; + context.fd = -1; try { // Wait for connection struct sockaddr_in client; socklen_t socklen = sizeof(client); memset(&client, 0, socklen); - fd = accept(monsocket, (struct sockaddr*)&client, &socklen); - if (fd < 0) { + context.fd = accept(monsocket, (struct sockaddr*)&client, &socklen); + if (context.fd < 0) { throw io_exception("accept() failed"); } // Read magic string char magic[6]; - int bytes_read = ReadNBytes(fd, (uint8_t *)magic, sizeof(magic)); + int bytes_read = ReadNBytes(context.fd, (uint8_t *)magic, sizeof(magic)); if (!bytes_read) { continue; } @@ -1421,19 +1418,22 @@ static void *MonThread(void *param) // Fetch the command PbCommand command; - DeserializeMessage(fd, command); + DeserializeMessage(context.fd, command); - if (!access_token.empty()) { - if (access_token != GetParam(command, "token")) { - ReturnStatus(fd, false, "Authentication failed", PbErrorCode::UNAUTHORIZED); - continue; - } + context.locale = GetParam(command, "locale"); + if (context.locale.empty()) { + context.locale = "en"; + } + + if (!access_token.empty() && access_token != GetParam(command, "token")) { + ReturnLocalizedError(context, ERROR_AUTHENTICATION, UNAUTHORIZED); + continue; } if (!PbOperation_IsValid(command.operation())) { LOGERROR("Received unknown command with operation opcode %d", command.operation()); - ReturnStatus(fd, false, "Unknown command", UNKNOWN_OPERATION); + ReturnLocalizedError(context, ERROR_OPERATION, UNKNOWN_OPERATION); continue; } @@ -1446,10 +1446,10 @@ static void *MonThread(void *param) string log_level = GetParam(command, "level"); bool status = SetLogLevel(log_level); if (!status) { - ReturnStatus(fd, false, "Invalid log level: " + log_level); + ReturnLocalizedError(context, ERROR_LOG_LEVEL, log_level); } else { - ReturnStatus(fd); + ReturnStatus(context); } break; } @@ -1457,23 +1457,23 @@ static void *MonThread(void *param) case DEFAULT_FOLDER: { string result = rascsi_image.SetDefaultImageFolder(GetParam(command, "folder")); if (!result.empty()) { - ReturnStatus(fd, false, result); + ReturnStatus(context, false, result); } else { - ReturnStatus(fd); + ReturnStatus(context); } break; } case DEVICES_INFO: { rascsi_response.GetDevicesInfo(result, command, devices, UnitNum); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case DEVICE_TYPES_INFO: { result.set_allocated_device_types_info(rascsi_response.GetDeviceTypesInfo(result, command)); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } @@ -1481,19 +1481,19 @@ static void *MonThread(void *param) result.set_allocated_server_info(rascsi_response.GetServerInfo( result, devices, reserved_ids, current_log_level, GetParam(command, "folder_pattern"), GetParam(command, "file_pattern"), rascsi_image.GetDepth())); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case VERSION_INFO: { result.set_allocated_version_info(rascsi_response.GetVersionInfo(result)); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case LOG_LEVEL_INFO: { result.set_allocated_log_level_info(rascsi_response.GetLogLevelInfo(result, current_log_level)); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } @@ -1501,14 +1501,14 @@ static void *MonThread(void *param) result.set_allocated_image_files_info(rascsi_response.GetAvailableImages(result, GetParam(command, "folder_pattern"), GetParam(command, "file_pattern"), rascsi_image.GetDepth())); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case IMAGE_FILE_INFO: { string filename = GetParam(command, "file"); if (filename.empty()) { - ReturnStatus(fd, false, "Can't get image file info: Missing filename"); + ReturnLocalizedError(context, ERROR_MISSING_FILENAME); } else { PbImageFile* image_file = new PbImageFile(); @@ -1516,10 +1516,10 @@ static void *MonThread(void *param) if (status) { result.set_status(true); result.set_allocated_image_file_info(image_file); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); } else { - ReturnStatus(fd, false, "Can't get image file info for '" + filename + "'"); + ReturnStatus(context, false, "Can't get image file info for '" + filename + "'"); } } break; @@ -1527,31 +1527,31 @@ static void *MonThread(void *param) case NETWORK_INTERFACES_INFO: { result.set_allocated_network_interfaces_info(rascsi_response.GetNetworkInterfacesInfo(result)); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case MAPPING_INFO: { result.set_allocated_mapping_info(rascsi_response.GetMappingInfo(result)); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case OPERATION_INFO: { result.set_allocated_operation_info(rascsi_response.GetOperationInfo(result, rascsi_image.GetDepth())); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case RESERVED_IDS_INFO: { result.set_allocated_reserved_ids_info(rascsi_response.GetReservedIds(result, reserved_ids)); - SerializeMessage(fd, result); + SerializeMessage(context.fd, result); break; } case SHUT_DOWN: { - ShutDown(fd, GetParam(command, "mode")); + ShutDown(context, GetParam(command, "mode")); break; } @@ -1561,7 +1561,7 @@ static void *MonThread(void *param) usleep(500 * 1000); } - ProcessCmd(fd, command); + ProcessCmd(context, command); break; } } @@ -1572,8 +1572,8 @@ static void *MonThread(void *param) // Fall through } - if (fd >= 0) { - close(fd); + if (context.fd >= 0) { + close(context.fd); } } diff --git a/src/raspberrypi/rascsi_image.cpp b/src/raspberrypi/rascsi_image.cpp index 8d235def..b171a759 100644 --- a/src/raspberrypi/rascsi_image.cpp +++ b/src/raspberrypi/rascsi_image.cpp @@ -16,7 +16,6 @@ #include "devices/file_support.h" #include "protobuf_util.h" #include "rascsi_image.h" -#include #include #include @@ -53,7 +52,7 @@ bool RascsiImage::CheckDepth(const string& filename) return count(filename.begin(), filename.end(), '/') <= depth; } -bool RascsiImage::CreateImageFolder(int fd, const string& filename) +bool RascsiImage::CreateImageFolder(const CommandContext& context, const string& filename) { size_t filename_start = filename.rfind('/'); if (filename_start != string::npos) { @@ -65,7 +64,7 @@ bool RascsiImage::CreateImageFolder(int fd, const string& filename) std::error_code error; filesystem::create_directories(folder, error); if (error) { - ReturnStatus(fd, false, "Can't create image folder '" + folder + "': " + strerror(errno)); + ReturnStatus(context, false, "Can't create image folder '" + folder + "': " + strerror(errno)); return false; } } @@ -130,25 +129,25 @@ bool RascsiImage::IsValidDstFilename(const string& filename) return stat(filename.c_str(), &st); } -bool RascsiImage::CreateImage(int fd, const PbCommand& command) +bool RascsiImage::CreateImage(const CommandContext& context, const PbCommand& command) { string filename = GetParam(command, "file"); if (filename.empty()) { - return ReturnStatus(fd, false, "Can't create image file: Missing image filename"); + return ReturnStatus(context, false, "Can't create image file: Missing image filename"); } if (!CheckDepth(filename)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); } string full_filename = default_image_folder + "/" + filename; if (!IsValidDstFilename(full_filename)) { - return ReturnStatus(fd, false, "Can't create image file: '" + full_filename + "': File already exists"); + return ReturnStatus(context, false, "Can't create image file: '" + full_filename + "': File already exists"); } const string size = GetParam(command, "size"); if (size.empty()) { - return ReturnStatus(fd, false, "Can't create image file '" + full_filename + "': Missing image size"); + return ReturnStatus(context, false, "Can't create image file '" + full_filename + "': Missing image size"); } off_t len; @@ -156,18 +155,16 @@ bool RascsiImage::CreateImage(int fd, const PbCommand& command) len = stoull(size); } catch(const invalid_argument& e) { - return ReturnStatus(fd, false, "Can't create image file '" + full_filename + "': Invalid file size " + size); + return ReturnStatus(context, false, "Can't create image file '" + full_filename + "': Invalid file size " + size); } catch(const out_of_range& e) { - return ReturnStatus(fd, false, "Can't create image file '" + full_filename + "': Invalid file size " + size); + return ReturnStatus(context, false, "Can't create image file '" + full_filename + "': Invalid file size " + size); } if (len < 512 || (len & 0x1ff)) { - ostringstream error; - error << "Invalid image file size " << len << " (not a multiple of 512)"; - return ReturnStatus(fd, false, error.str()); + return ReturnStatus(context, false, "Invalid image file size " + to_string(len) + " (not a multiple of 512)"); } - if (!CreateImageFolder(fd, full_filename)) { + if (!CreateImageFolder(context, full_filename)) { return false; } @@ -178,7 +175,7 @@ bool RascsiImage::CreateImage(int fd, const PbCommand& command) int image_fd = open(full_filename.c_str(), O_CREAT|O_WRONLY, permissions); if (image_fd == -1) { - return ReturnStatus(fd, false, "Can't create image file '" + full_filename + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't create image file '" + full_filename + "': " + string(strerror(errno))); } if (fallocate(image_fd, 0, 0, len)) { @@ -186,27 +183,26 @@ bool RascsiImage::CreateImage(int fd, const PbCommand& command) unlink(full_filename.c_str()); - return ReturnStatus(fd, false, "Can't allocate space for image file '" + full_filename + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't allocate space for image file '" + full_filename + "': " + string(strerror(errno))); } close(image_fd); - ostringstream msg; - msg << "Created " << (permissions & S_IWUSR ? "": "read-only ") << "image file '" << full_filename + "' with a size of " << len << " bytes"; - LOGINFO("%s", msg.str().c_str()); + LOGINFO("%s", string("Created " + string(permissions & S_IWUSR ? "": "read-only ") + "image file '" + full_filename + + "' with a size of " + to_string(len) + " bytes").c_str()); - return ReturnStatus(fd); + return ReturnStatus(context); } -bool RascsiImage::DeleteImage(int fd, const PbCommand& command) +bool RascsiImage::DeleteImage(const CommandContext& context, const PbCommand& command) { string filename = GetParam(command, "file"); if (filename.empty()) { - return ReturnStatus(fd, false, "Missing image filename"); + return ReturnStatus(context, false, "Missing image filename"); } if (!CheckDepth(filename)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); } string full_filename = default_image_folder + "/" + filename; @@ -216,13 +212,12 @@ bool RascsiImage::DeleteImage(int fd, const PbCommand& command) Filepath filepath; filepath.SetPath(full_filename.c_str()); if (FileSupport::GetIdsForReservedFile(filepath, id, unit)) { - ostringstream msg; - msg << "Can't delete image file '" << full_filename << "', it is currently being used by device ID " << id << ", unit " << unit; - return ReturnStatus(fd, false, msg.str()); + return ReturnStatus(context, false, "Can't delete image file '" + full_filename + + "', it is currently being used by device ID " + to_string(id) + ", unit " + to_string(unit)); } if (remove(full_filename.c_str())) { - return ReturnStatus(fd, false, "Can't delete image file '" + full_filename + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't delete image file '" + full_filename + "': " + string(strerror(errno))); } // Delete empty subfolders @@ -237,7 +232,7 @@ bool RascsiImage::DeleteImage(int fd, const PbCommand& command) } if (remove(full_folder.c_str())) { - return ReturnStatus(fd, false, "Can't delete empty image folder '" + full_folder + "'"); + return ReturnStatus(context, false, "Can't delete empty image folder '" + full_folder + "'"); } last_slash = folder.rfind('/'); @@ -245,105 +240,105 @@ bool RascsiImage::DeleteImage(int fd, const PbCommand& command) LOGINFO("Deleted image file '%s'", full_filename.c_str()); - return ReturnStatus(fd); + return ReturnStatus(context); } -bool RascsiImage::RenameImage(int fd, const PbCommand& command) +bool RascsiImage::RenameImage(const CommandContext& context, const PbCommand& command) { string from = GetParam(command, "from"); if (from.empty()) { - return ReturnStatus(fd, false, "Can't rename image file: Missing source filename"); + return ReturnStatus(context, false, "Can't rename/move image file: Missing source filename"); } if (!CheckDepth(from)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + from + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + from + "'").c_str()); } from = default_image_folder + "/" + from; if (!IsValidSrcFilename(from)) { - return ReturnStatus(fd, false, "Can't rename image file: '" + from + "': Invalid name or type"); + return ReturnStatus(context, false, "Can't rename/move image file: '" + from + "': Invalid name or type"); } string to = GetParam(command, "to"); if (to.empty()) { - return ReturnStatus(fd, false, "Can't rename image file '" + from + "': Missing destination filename"); + return ReturnStatus(context, false, "Can't rename/move image file '" + from + "': Missing destination filename"); } if (!CheckDepth(to)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + to + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + to + "'").c_str()); } to = default_image_folder + "/" + to; if (!IsValidDstFilename(to)) { - return ReturnStatus(fd, false, "Can't rename image file '" + from + "' to '" + to + "': File already exists"); + return ReturnStatus(context, false, "Can't rename/move image file '" + from + "' to '" + to + "': File already exists"); } - if (!CreateImageFolder(fd, to)) { + if (!CreateImageFolder(context, to)) { return false; } if (rename(from.c_str(), to.c_str())) { - return ReturnStatus(fd, false, "Can't rename image file '" + from + "' to '" + to + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't rename/move image file '" + from + "' to '" + to + "': " + string(strerror(errno))); } - LOGINFO("Renamed image file '%s' to '%s'", from.c_str(), to.c_str()); + LOGINFO("Renamed/Moved image file '%s' to '%s'", from.c_str(), to.c_str()); - return ReturnStatus(fd); + return ReturnStatus(context); } -bool RascsiImage::CopyImage(int fd, const PbCommand& command) +bool RascsiImage::CopyImage(const CommandContext& context, const PbCommand& command) { string from = GetParam(command, "from"); if (from.empty()) { - return ReturnStatus(fd, false, "Can't copy image file: Missing source filename"); + return ReturnStatus(context, false, "Can't copy image file: Missing source filename"); } if (!CheckDepth(from)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + from + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + from + "'").c_str()); } from = default_image_folder + "/" + from; if (!IsValidSrcFilename(from)) { - return ReturnStatus(fd, false, "Can't copy image file: '" + from + "': Invalid name or type"); + return ReturnStatus(context, false, "Can't copy image file: '" + from + "': Invalid name or type"); } string to = GetParam(command, "to"); if (to.empty()) { - return ReturnStatus(fd, false, "Can't copy image file '" + from + "': Missing destination filename"); + return ReturnStatus(context, false, "Can't copy image file '" + from + "': Missing destination filename"); } if (!CheckDepth(to)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + to + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + to + "'").c_str()); } to = default_image_folder + "/" + to; if (!IsValidDstFilename(to)) { - return ReturnStatus(fd, false, "Can't copy image file '" + from + "' to '" + to + "': File already exists"); + return ReturnStatus(context, false, "Can't copy image file '" + from + "' to '" + to + "': File already exists"); } struct stat st; if (lstat(from.c_str(), &st)) { - return ReturnStatus(fd, false, "Can't access source image file '" + from + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't access source image file '" + from + "': " + string(strerror(errno))); } - if (!CreateImageFolder(fd, to)) { + if (!CreateImageFolder(context, to)) { return false; } // Symbolic links need a special handling if ((st.st_mode & S_IFMT) == S_IFLNK) { if (symlink(filesystem::read_symlink(from).c_str(), to.c_str())) { - return ReturnStatus(fd, false, "Can't copy symlink '" + from + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't copy symlink '" + from + "': " + string(strerror(errno))); } LOGINFO("Copied symlink '%s' to '%s'", from.c_str(), to.c_str()); - return ReturnStatus(fd); + return ReturnStatus(context); } int fd_src = open(from.c_str(), O_RDONLY, 0); if (fd_src == -1) { - return ReturnStatus(fd, false, "Can't open source image file '" + from + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't open source image file '" + from + "': " + string(strerror(errno))); } string permission = GetParam(command, "read_only"); @@ -355,7 +350,7 @@ bool RascsiImage::CopyImage(int fd, const PbCommand& command) if (fd_dst == -1) { close(fd_src); - return ReturnStatus(fd, false, "Can't open destination image file '" + to + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't open destination image file '" + to + "': " + string(strerror(errno))); } if (sendfile(fd_dst, fd_src, 0, st.st_size) == -1) { @@ -364,7 +359,7 @@ bool RascsiImage::CopyImage(int fd, const PbCommand& command) unlink(to.c_str()); - return ReturnStatus(fd, false, "Can't copy image file '" + from + "' to '" + to + "': " + string(strerror(errno))); + return ReturnStatus(context, false, "Can't copy image file '" + from + "' to '" + to + "': " + string(strerror(errno))); } close(fd_dst); @@ -372,23 +367,23 @@ bool RascsiImage::CopyImage(int fd, const PbCommand& command) LOGINFO("Copied image file '%s' to '%s'", from.c_str(), to.c_str()); - return ReturnStatus(fd); + return ReturnStatus(context); } -bool RascsiImage::SetImagePermissions(int fd, const PbCommand& command) +bool RascsiImage::SetImagePermissions(const CommandContext& context, const PbCommand& command) { string filename = GetParam(command, "file"); if (filename.empty()) { - return ReturnStatus(fd, false, "Missing image filename"); + return ReturnStatus(context, false, "Missing image filename"); } if (!CheckDepth(filename)) { - return ReturnStatus(fd, false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); + return ReturnStatus(context, false, ("Invalid folder hierarchy depth '" + filename + "'").c_str()); } filename = default_image_folder + "/" + filename; if (!IsValidSrcFilename(filename)) { - return ReturnStatus(fd, false, "Can't modify image file '" + filename + "': Invalid name or type"); + return ReturnStatus(context, false, "Can't modify image file '" + filename + "': Invalid name or type"); } bool protect = command.operation() == PROTECT_IMAGE; @@ -396,9 +391,8 @@ bool RascsiImage::SetImagePermissions(int fd, const PbCommand& command) int permissions = protect ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; if (chmod(filename.c_str(), permissions) == -1) { - ostringstream error; - error << "Can't " << (protect ? "protect" : "unprotect") << " image file '" << filename << "': " << strerror(errno); - return ReturnStatus(fd, false, error.str()); + return ReturnStatus(context, false, "Can't " + string(protect ? "protect" : "unprotect") + " image file '" + filename + "': " + + strerror(errno)); } if (protect) { @@ -408,5 +402,5 @@ bool RascsiImage::SetImagePermissions(int fd, const PbCommand& command) LOGINFO("Unprotected image file '%s'", filename.c_str()); } - return ReturnStatus(fd); + return ReturnStatus(context); } diff --git a/src/raspberrypi/rascsi_image.h b/src/raspberrypi/rascsi_image.h index debbdd04..be1d828a 100644 --- a/src/raspberrypi/rascsi_image.h +++ b/src/raspberrypi/rascsi_image.h @@ -10,6 +10,7 @@ #pragma once #include "rascsi_interface.pb.h" +#include "command_context.h" #include using namespace std; @@ -25,16 +26,16 @@ public: void SetDepth(int depth) { this->depth = depth; } int GetDepth() { return depth; } bool CheckDepth(const string&); - bool CreateImageFolder(int, const string&); + bool CreateImageFolder(const CommandContext&, const string&); string GetDefaultImageFolder() const { return default_image_folder; } string SetDefaultImageFolder(const string&); bool IsValidSrcFilename(const string&); bool IsValidDstFilename(const string&); - bool CreateImage(int, const PbCommand&); - bool DeleteImage(int, const PbCommand&); - bool RenameImage(int, const PbCommand&); - bool CopyImage(int, const PbCommand&); - bool SetImagePermissions(int, const PbCommand&); + bool CreateImage(const CommandContext&, const PbCommand&); + bool DeleteImage(const CommandContext&, const PbCommand&); + bool RenameImage(const CommandContext&, const PbCommand&); + bool CopyImage(const CommandContext&, const PbCommand&); + bool SetImagePermissions(const CommandContext&, const PbCommand&); private: diff --git a/src/raspberrypi/rascsi_interface.proto b/src/raspberrypi/rascsi_interface.proto index f2d22d31..70bcb9e0 100644 --- a/src/raspberrypi/rascsi_interface.proto +++ b/src/raspberrypi/rascsi_interface.proto @@ -3,7 +3,8 @@ // A message starts with a little endian 32 bit header which contains the protobuf message size. // Unless explicitly specified the order of repeated data returned is undefined. // All operations accept an optional access token, specified by the "token" parameter. -// Only the VERSION_INFO operation never requires authentication. +// All operations also accept an optional locale, specified with the "locale" parameter. If there is +// a localized error message rascsi returns it, with English being the fallback language. // syntax = "proto3"; diff --git a/src/raspberrypi/rascsi_response.cpp b/src/raspberrypi/rascsi_response.cpp index 8ac41f13..2e2c3aba 100644 --- a/src/raspberrypi/rascsi_response.cpp +++ b/src/raspberrypi/rascsi_response.cpp @@ -16,7 +16,6 @@ #include "rascsi_interface.pb.h" #include "rascsi_image.h" #include "rascsi_response.h" -#include using namespace rascsi_interface; using namespace protobuf_util; @@ -261,10 +260,8 @@ void RascsiResponse::GetDevicesInfo(PbResult& result, const PbCommand& command, id_sets.insert(make_pair(device.id(), device.unit())); } else { - ostringstream error; - error << "No device for ID " << device.id() << ", unit " << device.unit(); result.set_status(false); - result.set_msg(error.str()); + result.set_msg("No device for ID " + to_string(device.id()) + ", unit " + to_string(device.unit())); return; } } diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp index 398831ac..4ce69b68 100644 --- a/src/raspberrypi/rasctl.cpp +++ b/src/raspberrypi/rasctl.cpp @@ -16,6 +16,7 @@ #include "rasutil.h" #include "rasctl_commands.h" #include "rascsi_interface.pb.h" +#include #include #include @@ -118,7 +119,8 @@ int main(int argc, char* argv[]) cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl; cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] "; cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] "; - cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] "; + cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] "; + cerr << "[-x CURRENT_NAME:NEW_NAME] [-z LOCALE] "; cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [o] [-O] [-s] [-v] [-V] [-y] [-X]" << endl; cerr << " where ID := {0-7}" << endl; cerr << " UNIT := {0-31}, default is 0" << endl; @@ -154,9 +156,14 @@ int main(int argc, char* argv[]) string token; bool list = false; + string locale = setlocale(LC_MESSAGES, ""); + if (locale == "C") { + locale = "en"; + } + opterr = 1; int opt; - while ((opt = getopt(argc, argv, "e::lmos::vDINOTVXa:b:c:d:f:h:i:n:p:r:t:u:x:C:E:F:L:P::R:")) != -1) { + while ((opt = getopt(argc, argv, "e::lmos::vDINOTVXa:b:c:d:f:h:i:n:p:r:t:u:x:z:C:E:F:L:P::R:")) != -1) { switch (opt) { case 'i': { int id; @@ -350,6 +357,10 @@ int main(int argc, char* argv[]) command.set_operation(SHUT_DOWN); AddParam(command, "mode", "rascsi"); break; + + case 'z': + locale = optarg; + break; } } @@ -361,7 +372,7 @@ int main(int argc, char* argv[]) if (list) { PbCommand command_list; command_list.set_operation(DEVICES_INFO); - RasctlCommands rasctl_commands(command_list, hostname, port, token); + RasctlCommands rasctl_commands(command_list, hostname, port, token, locale); rasctl_commands.CommandDevicesInfo(); exit(EXIT_SUCCESS); } @@ -372,7 +383,7 @@ int main(int argc, char* argv[]) AddParam(*device, "file", param); } - RasctlCommands rasctl_commands(command, hostname, port, token); + RasctlCommands rasctl_commands(command, hostname, port, token, locale); switch(command.operation()) { case LOG_LEVEL: diff --git a/src/raspberrypi/rasctl_commands.cpp b/src/raspberrypi/rasctl_commands.cpp index a91c1131..af4e21e3 100644 --- a/src/raspberrypi/rasctl_commands.cpp +++ b/src/raspberrypi/rasctl_commands.cpp @@ -25,12 +25,14 @@ using namespace std; using namespace rascsi_interface; using namespace protobuf_util; -RasctlCommands::RasctlCommands(PbCommand& command, const string& hostname, int port, const string& token) +RasctlCommands::RasctlCommands(PbCommand& command, const string& hostname, int port, const string& token, + const string& locale) { this->command = command; this->hostname = hostname; this->port = port; this->token = token; + this->locale = locale; } void RasctlCommands::SendCommand() @@ -39,6 +41,10 @@ void RasctlCommands::SendCommand() AddParam(command, "token", token); } + if (!locale.empty()) { + AddParam(command, "locale", locale); + } + // Send command int fd = -1; try { diff --git a/src/raspberrypi/rasctl_commands.h b/src/raspberrypi/rasctl_commands.h index 2e35193f..35c3f8a2 100644 --- a/src/raspberrypi/rasctl_commands.h +++ b/src/raspberrypi/rasctl_commands.h @@ -20,7 +20,7 @@ class RasctlCommands { public: - RasctlCommands(PbCommand&, const string&, int, const string&); + RasctlCommands(PbCommand&, const string&, int, const string&, const string&); ~RasctlCommands() {}; void SendCommand(); @@ -50,6 +50,7 @@ private: string hostname; int port; string token; + string locale; PbResult result;