From f00738fe3a38e2d49be34fb9b7913d029e681ef0 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Sun, 5 Sep 2021 10:09:18 +0500 Subject: [PATCH] Changed: Make sure full path is included in FileUtilsErrnos Previously, `FileUtilsErrno` had some errors that didn't include the full path passed to the `FileUtils` functions and caller had to manually append the path to the error. This was done due to `termux-tasker` plugin config activity was using these errors in the executable and working directory text fields and we had to keep the error short as possible to reduce clutter. Now by default, the path will be included so that its not missing for other cases and the `FileUtils.getShortFileUtilsError()` function is provided to get a shorter version from the original error if its possible to do so if caller like `termux-tasker` requires it. --- .../com/termux/app/RunCommandService.java | 2 - app/src/main/res/values/strings.xml | 6 -- .../com/termux/shared/file/FileUtils.java | 88 +++++++++++++------ .../termux/shared/models/errors/Errno.java | 25 +++++- .../termux/shared/models/errors/Error.java | 15 +++- .../shared/models/errors/FileUtilsErrno.java | 48 +++++++--- 6 files changed, 135 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/termux/app/RunCommandService.java b/app/src/main/java/com/termux/app/RunCommandService.java index bc4d6451..f54f1693 100644 --- a/app/src/main/java/com/termux/app/RunCommandService.java +++ b/app/src/main/java/com/termux/app/RunCommandService.java @@ -148,7 +148,6 @@ public class RunCommandService extends Service { FileUtils.APP_EXECUTABLE_FILE_PERMISSIONS, true, true, false); if (error != null) { - error.appendMessage("\n" + this.getString(R.string.msg_executable_absolute_path, executionCommand.executable)); executionCommand.setStateFailed(error); PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); return stopService(); @@ -170,7 +169,6 @@ public class RunCommandService extends Service { true, true, true, false, true); if (error != null) { - error.appendMessage("\n" + this.getString(R.string.msg_working_directory_absolute_path, executionCommand.workingDirectory)); executionCommand.setStateFailed(error); PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false); return stopService(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6b37c06b..192eddd5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -111,12 +111,6 @@ - - Executable Absolute Path: \"%1$s\" - Working Directory Absolute Path: \"%1$s\" - - - Save file in ~/downloads/ Edit diff --git a/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java b/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java index dd057e4c..c1b5b6fd 100644 --- a/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java @@ -10,6 +10,7 @@ import com.termux.shared.file.filesystem.FileType; import com.termux.shared.file.filesystem.FileTypes; import com.termux.shared.data.DataUtils; import com.termux.shared.logger.Logger; +import com.termux.shared.models.errors.Errno; import com.termux.shared.models.errors.Error; import com.termux.shared.models.errors.FileUtilsErrno; import com.termux.shared.models.errors.FunctionErrno; @@ -34,6 +35,7 @@ import java.nio.file.LinkOption; import java.nio.file.StandardCopyOption; import java.util.Calendar; import java.util.Iterator; +import java.util.List; import java.util.regex.Pattern; public class FileUtils { @@ -260,7 +262,7 @@ public class FileUtils { // If file exists but not a regular file if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) { - return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file"); + return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file"); } boolean isPathUnderParentDirPath = false; @@ -283,7 +285,8 @@ public class FileUtils { // If path is not a regular file // Regular files cannot be automatically created so we do not ignore if missing if (fileType != FileType.REGULAR) { - return FileUtilsErrno.ERRNO_NO_REGULAR_FILE_FOUND.getError(label + "file"); + label += "regular file"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label); } // If there is not parentDirPath restriction or path is not under parentDirPath or @@ -341,7 +344,7 @@ public class FileUtils { // If file exists but not a directory file if (fileType != FileType.NO_EXIST && fileType != FileType.DIRECTORY) { - return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory"); + return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory", filePath).setLabel(label + "directory"); } boolean isPathInParentDirPath = false; @@ -380,7 +383,8 @@ public class FileUtils { // If path is not a directory // Directories can be automatically created so we can ignore if missing with above check if (fileType != FileType.DIRECTORY) { - return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "directory", filePath); + label += "directory"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label); } if (permissionsToCheck != null) { @@ -455,7 +459,7 @@ public class FileUtils { // If file exists but not a regular file if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) { - return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file"); + return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file"); } // If regular file already exists @@ -645,8 +649,10 @@ public class FileUtils { // If target file does not exist if (targetFileType == FileType.NO_EXIST) { // If dangling symlink should not be allowed, then return with error - if (!allowDangling) - return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "symlink target file", targetFileAbsolutePath); + if (!allowDangling) { + label += "symlink target file"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, targetFileAbsolutePath).setLabel(label); + } } // If destination exists @@ -920,8 +926,10 @@ public class FileUtils { if (ignoreNonExistentSrcFile) return null; // Else return with error - else - return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "source file", srcFilePath); + else { + label += "source file"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, srcFilePath).setLabel(label); + } } // If the file type of the source file does not exist in the allowedFileTypeFlags, then return with error @@ -1121,8 +1129,10 @@ public class FileUtils { if (ignoreNonExistentFile) return null; // Else return with error - else - return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "file meant to be deleted", filePath); + else { + label += "file meant to be deleted"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label); + } } // If the file type of the file does not exist in the allowedFileTypeFlags @@ -1224,7 +1234,7 @@ public class FileUtils { // If file exists but not a directory file if (fileType != FileType.NO_EXIST && fileType != FileType.DIRECTORY) { - return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory"); + return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory", filePath).setLabel(label + "directory"); } // If directory exists, clear its contents @@ -1288,7 +1298,7 @@ public class FileUtils { // If file exists but not a directory file if (fileType != FileType.NO_EXIST && fileType != FileType.DIRECTORY) { - return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory"); + return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory", filePath).setLabel(label + "directory"); } // If file does not exist @@ -1297,8 +1307,10 @@ public class FileUtils { if (ignoreNonExistentFile) return null; // Else return with error - else - return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "directory under which files had to be deleted", filePath); + else { + label += "directory under which files had to be deleted"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label); + } } // If directory exists, delete its contents @@ -1349,7 +1361,7 @@ public class FileUtils { // If file exists but not a regular file if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) { - return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file"); + return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file"); } // If file does not exist @@ -1358,8 +1370,10 @@ public class FileUtils { if (ignoreNonExistentFile) return null; // Else return with error - else - return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "file meant to be read", filePath); + else { + label += "file meant to be read"; + return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label); + } } if (charset == null) charset = Charset.defaultCharset(); @@ -1428,7 +1442,7 @@ public class FileUtils { // If file exists but not a regular file if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) { - return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file"), null); + return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file"), null); } // If file does not exist @@ -1437,8 +1451,10 @@ public class FileUtils { if (ignoreNonExistentFile) return new ReadSerializableObjectResult(null, null); // Else return with error - else - return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "file meant to be read", filePath), null); + else { + label += "file meant to be read"; + return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label), null); + } } FileInputStream fileInputStream = null; @@ -1556,7 +1572,7 @@ public class FileUtils { // If file exists but not a regular file if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) { - return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file"); + return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file"); } // Create the file parent directory @@ -1764,17 +1780,17 @@ public class FileUtils { // If file is not readable if (permissionsToCheck.contains("r") && !file.canRead()) { - return FileUtilsErrno.ERRNO_FILE_NOT_READABLE.getError(label + "file"); + return FileUtilsErrno.ERRNO_FILE_NOT_READABLE.getError(label + "file", filePath).setLabel(label + "file"); } // If file is not writable if (permissionsToCheck.contains("w") && !file.canWrite()) { - return FileUtilsErrno.ERRNO_FILE_NOT_WRITABLE.getError(label + "file"); + return FileUtilsErrno.ERRNO_FILE_NOT_WRITABLE.getError(label + "file", filePath).setLabel(label + "file"); } // If file is not executable // This canExecute() will give "avc: granted { execute }" warnings for target sdk 29 else if (permissionsToCheck.contains("x") && !file.canExecute() && !ignoreIfNotExecutable) { - return FileUtilsErrno.ERRNO_FILE_NOT_EXECUTABLE.getError(label + "file"); + return FileUtilsErrno.ERRNO_FILE_NOT_EXECUTABLE.getError(label + "file", filePath).setLabel(label + "file"); } return null; @@ -1794,4 +1810,26 @@ public class FileUtils { return Pattern.compile("^([r-])[w-][x-]$", 0).matcher(string).matches(); } + + + /** + * Get a {@link Error} that contains a shorter version of {@link Errno} message. + * + * @param error The original {@link Error} returned by one of the {@link FileUtils} functions. + * @return Returns the shorter {@link Error} if one exists, otherwise original {@code error}. + */ + public static Error getShortFileUtilsError(final Error error) { + String type = error.getType(); + if (!FileUtilsErrno.TYPE.equals(type)) return error; + + Errno shortErrno = FileUtilsErrno.ERRNO_SHORT_MAPPING.get(Errno.valueOf(type, error.getCode())); + if (shortErrno == null) return error; + + List throwables = error.getThrowablesList(); + if (throwables.isEmpty()) + return shortErrno.getError(DataUtils.getDefaultIfNull(error.getLabel(), "file")); + else + return shortErrno.getError(throwables, error.getLabel(), "file"); + } + } diff --git a/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java b/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java index ce4c702d..d330787c 100644 --- a/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java +++ b/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java @@ -8,11 +8,14 @@ import com.termux.shared.logger.Logger; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; /** The {@link Class} that defines error messages and codes. */ public class Errno { + private static final HashMap map = new HashMap<>(); + public static final String TYPE = "Error"; @@ -35,6 +38,7 @@ public class Errno { this.type = type; this.code = code; this.message = message; + map.put(type + ":" + code, this); } @NonNull @@ -56,6 +60,17 @@ public class Errno { return code; } + /** + * Get the {@link Errno} of a specific type and code. + * + * @param type The unique type of the {@link Errno}. + * @param code The unique code of the {@link Errno}. + */ + public static Errno valueOf(String type, Integer code) { + if (type == null || type.isEmpty() || code == null) return null; + return map.get(type + ":" + code); + } + public Error getError() { @@ -73,12 +88,18 @@ public class Errno { } public Error getError(Throwable throwable, Object... args) { - return getError(Collections.singletonList(throwable), args); + if (throwable == null) + return getError(args); + else + return getError(Collections.singletonList(throwable), args); } public Error getError(List throwablesList, Object... args) { try { - return new Error(getType(), getCode(), String.format(getMessage(), args), throwablesList); + if (throwablesList == null) + return new Error(getType(), getCode(), String.format(getMessage(), args)); + else + return new Error(getType(), getCode(), String.format(getMessage(), args), throwablesList); } catch (Exception e) { Logger.logWarn(LOG_TAG, "Exception raised while calling String.format() for error message of errno " + this + " with args" + Arrays.toString(args) + "\n" + e.getMessage()); // Return unformatted message as a backup diff --git a/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java b/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java index b9dba33f..f74f4485 100644 --- a/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java +++ b/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java @@ -12,6 +12,8 @@ import java.util.List; public class Error implements Serializable { + /** The optional error label. */ + private String label; /** The error type. */ private String type; /** The error code. */ @@ -76,7 +78,18 @@ public class Error implements Serializable { this.code = Errno.ERRNO_SUCCESS.getCode(); this.message = message; - this.throwablesList = throwablesList; + + if (throwablesList != null) + this.throwablesList = throwablesList; + } + + public Error setLabel(String label) { + this.label = label; + return this; + } + + public String getLabel() { + return label; } diff --git a/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java b/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java index 48b4b096..f8c701d8 100644 --- a/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java +++ b/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java @@ -1,5 +1,8 @@ package com.termux.shared.models.errors; +import java.util.HashMap; +import java.util.Map; + /** The {@link Class} that defines FileUtils error messages and codes. */ public class FileUtilsErrno extends Errno { @@ -18,19 +21,20 @@ public class FileUtilsErrno extends Errno { /* Errors for invalid or not found files at path (150-200) */ - public static final Errno ERRNO_FILE_NOT_FOUND_AT_PATH = new Errno(TYPE, 150, "The %1$s is not found at path \"%2$s\"."); + public static final Errno ERRNO_FILE_NOT_FOUND_AT_PATH = new Errno(TYPE, 150, "The %1$s not found at path \"%2$s\"."); + public static final Errno ERRNO_FILE_NOT_FOUND_AT_PATH_SHORT = new Errno(TYPE, 151, "The %1$s not found at path."); - public static final Errno ERRNO_NO_REGULAR_FILE_FOUND = new Errno(TYPE, 151, "Regular file not found at %1$s path."); - public static final Errno ERRNO_NOT_A_REGULAR_FILE = new Errno(TYPE, 152, "The %1$s at path \"%2$s\" is not a regular file."); + public static final Errno ERRNO_NON_REGULAR_FILE_FOUND = new Errno(TYPE, 152, "Non-regular file found at %1$s path \"%2$s\"."); + public static final Errno ERRNO_NON_REGULAR_FILE_FOUND_SHORT = new Errno(TYPE, 153, "Non-regular file found at %1$s path."); + public static final Errno ERRNO_NON_DIRECTORY_FILE_FOUND = new Errno(TYPE, 154, "Non-directory file found at %1$s path \"%2$s\"."); + public static final Errno ERRNO_NON_DIRECTORY_FILE_FOUND_SHORT = new Errno(TYPE, 155, "Non-directory file found at %1$s path."); + public static final Errno ERRNO_NON_SYMLINK_FILE_FOUND = new Errno(TYPE, 156, "Non-symlink file found at %1$s path \"%2$s\"."); + public static final Errno ERRNO_NON_SYMLINK_FILE_FOUND_SHORT = new Errno(TYPE, 157, "Non-symlink file found at %1$s path."); - public static final Errno ERRNO_NON_REGULAR_FILE_FOUND = new Errno(TYPE, 153, "Non-regular file found at %1$s path."); - public static final Errno ERRNO_NON_DIRECTORY_FILE_FOUND = new Errno(TYPE, 154, "Non-directory file found at %1$s path."); - public static final Errno ERRNO_NON_SYMLINK_FILE_FOUND = new Errno(TYPE, 155, "Non-symlink file found at %1$s path."); + public static final Errno ERRNO_FILE_NOT_AN_ALLOWED_FILE_TYPE = new Errno(TYPE, 158, "The %1$s found at path \"%2$s\" is not one of allowed file types \"%3$s\"."); - public static final Errno ERRNO_FILE_NOT_AN_ALLOWED_FILE_TYPE = new Errno(TYPE, 156, "The %1$s found at path \"%2$s\" is not one of allowed file types \"%3$s\"."); - - public static final Errno ERRNO_VALIDATE_FILE_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 157, "Validating file existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s"); - public static final Errno ERRNO_VALIDATE_DIRECTORY_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 158, "Validating directory existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s"); + public static final Errno ERRNO_VALIDATE_FILE_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 159, "Validating file existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s"); + public static final Errno ERRNO_VALIDATE_DIRECTORY_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 160, "Validating directory existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s"); @@ -72,13 +76,31 @@ public class FileUtilsErrno extends Errno { /* Errors for invalid file permissions (400-450) */ public static final Errno ERRNO_INVALID_FILE_PERMISSIONS_STRING_TO_CHECK = new Errno(TYPE, 400, "The file permission string to check is invalid."); - public static final Errno ERRNO_FILE_NOT_READABLE = new Errno(TYPE, 401, "The %1$s at path is not readable. Permission Denied."); - public static final Errno ERRNO_FILE_NOT_WRITABLE = new Errno(TYPE, 402, "The %1$s at path is not writable. Permission Denied."); - public static final Errno ERRNO_FILE_NOT_EXECUTABLE = new Errno(TYPE, 403, "The %1$s at path is not executable. Permission Denied."); + public static final Errno ERRNO_FILE_NOT_READABLE = new Errno(TYPE, 401, "The %1$s at path \"%2$s\" is not readable. Permission Denied."); + public static final Errno ERRNO_FILE_NOT_READABLE_SHORT = new Errno(TYPE, 402, "The %1$s at path is not readable. Permission Denied."); + public static final Errno ERRNO_FILE_NOT_WRITABLE = new Errno(TYPE, 403, "The %1$s at path \"%2$s\" is not writable. Permission Denied."); + public static final Errno ERRNO_FILE_NOT_WRITABLE_SHORT = new Errno(TYPE, 404, "The %1$s at path is not writable. Permission Denied."); + public static final Errno ERRNO_FILE_NOT_EXECUTABLE = new Errno(TYPE, 405, "The %1$s at path \"%2$s\" is not executable. Permission Denied."); + public static final Errno ERRNO_FILE_NOT_EXECUTABLE_SHORT = new Errno(TYPE, 406, "The %1$s at path is not executable. Permission Denied."); FileUtilsErrno(final String type, final int code, final String message) { super(type, code, message); } + + + /** Defines the {@link Errno} mapping to get a shorter version of {@link FileUtilsErrno}. */ + public static Map ERRNO_SHORT_MAPPING = new HashMap() {{ + put(ERRNO_FILE_NOT_FOUND_AT_PATH, ERRNO_FILE_NOT_FOUND_AT_PATH_SHORT); + + put(ERRNO_NON_REGULAR_FILE_FOUND, ERRNO_NON_REGULAR_FILE_FOUND_SHORT); + put(ERRNO_NON_DIRECTORY_FILE_FOUND, ERRNO_NON_DIRECTORY_FILE_FOUND_SHORT); + put(ERRNO_NON_SYMLINK_FILE_FOUND, ERRNO_NON_SYMLINK_FILE_FOUND_SHORT); + + put(ERRNO_FILE_NOT_READABLE, ERRNO_FILE_NOT_READABLE_SHORT); + put(ERRNO_FILE_NOT_WRITABLE, ERRNO_FILE_NOT_WRITABLE_SHORT); + put(ERRNO_FILE_NOT_EXECUTABLE, ERRNO_FILE_NOT_EXECUTABLE_SHORT); + }}; + }