Prechádzať zdrojové kódy

[FileAccess] Add methods to get/set "hidden" and "read-only" attributes on macOS/BSD and Windows.

bruvzg 1 rok pred
rodič
commit
8aa6f29b56

+ 70 - 4
core/io/file_access.cpp

@@ -583,7 +583,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
 	return mt;
 }
 
-uint32_t FileAccess::get_unix_permissions(const String &p_file) {
+BitField<FileAccess::UnixPermissionFlags> FileAccess::get_unix_permissions(const String &p_file) {
 	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
 		return 0;
 	}
@@ -591,11 +591,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
 	Ref<FileAccess> fa = create_for_path(p_file);
 	ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
 
-	uint32_t mt = fa->_get_unix_permissions(p_file);
-	return mt;
+	return fa->_get_unix_permissions(p_file);
 }
 
-Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+Error FileAccess::set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) {
 	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
 		return ERR_UNAVAILABLE;
 	}
@@ -607,6 +606,52 @@ Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissi
 	return err;
 }
 
+bool FileAccess::get_hidden_attribute(const String &p_file) {
+	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+		return false;
+	}
+
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), false, "Cannot create FileAccess for path '" + p_file + "'.");
+
+	return fa->_get_hidden_attribute(p_file);
+}
+
+Error FileAccess::set_hidden_attribute(const String &p_file, bool p_hidden) {
+	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+		return ERR_UNAVAILABLE;
+	}
+
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+
+	Error err = fa->_set_hidden_attribute(p_file, p_hidden);
+	return err;
+}
+
+bool FileAccess::get_read_only_attribute(const String &p_file) {
+	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+		return false;
+	}
+
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), false, "Cannot create FileAccess for path '" + p_file + "'.");
+
+	return fa->_get_read_only_attribute(p_file);
+}
+
+Error FileAccess::set_read_only_attribute(const String &p_file, bool p_ro) {
+	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+		return ERR_UNAVAILABLE;
+	}
+
+	Ref<FileAccess> fa = create_for_path(p_file);
+	ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+
+	Error err = fa->_set_read_only_attribute(p_file, p_ro);
+	return err;
+}
+
 void FileAccess::store_string(const String &p_string) {
 	if (p_string.length() == 0) {
 		return;
@@ -865,6 +910,14 @@ void FileAccess::_bind_methods() {
 	ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists);
 	ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time);
 
+	ClassDB::bind_static_method("FileAccess", D_METHOD("get_unix_permissions", "file"), &FileAccess::get_unix_permissions);
+	ClassDB::bind_static_method("FileAccess", D_METHOD("set_unix_permissions", "file", "permissions"), &FileAccess::set_unix_permissions);
+
+	ClassDB::bind_static_method("FileAccess", D_METHOD("get_hidden_attribute", "file"), &FileAccess::get_hidden_attribute);
+	ClassDB::bind_static_method("FileAccess", D_METHOD("set_hidden_attribute", "file", "hidden"), &FileAccess::set_hidden_attribute);
+	ClassDB::bind_static_method("FileAccess", D_METHOD("set_read_only_attribute", "file", "ro"), &FileAccess::set_read_only_attribute);
+	ClassDB::bind_static_method("FileAccess", D_METHOD("get_read_only_attribute", "file"), &FileAccess::get_read_only_attribute);
+
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian");
 
 	BIND_ENUM_CONSTANT(READ);
@@ -877,4 +930,17 @@ void FileAccess::_bind_methods() {
 	BIND_ENUM_CONSTANT(COMPRESSION_ZSTD);
 	BIND_ENUM_CONSTANT(COMPRESSION_GZIP);
 	BIND_ENUM_CONSTANT(COMPRESSION_BROTLI);
+
+	BIND_BITFIELD_FLAG(UNIX_READ_OWNER);
+	BIND_BITFIELD_FLAG(UNIX_WRITE_OWNER);
+	BIND_BITFIELD_FLAG(UNIX_EXECUTE_OWNER);
+	BIND_BITFIELD_FLAG(UNIX_READ_GROUP);
+	BIND_BITFIELD_FLAG(UNIX_WRITE_GROUP);
+	BIND_BITFIELD_FLAG(UNIX_EXECUTE_GROUP);
+	BIND_BITFIELD_FLAG(UNIX_READ_OTHER);
+	BIND_BITFIELD_FLAG(UNIX_WRITE_OTHER);
+	BIND_BITFIELD_FLAG(UNIX_EXECUTE_OTHER);
+	BIND_BITFIELD_FLAG(UNIX_SET_USER_ID);
+	BIND_BITFIELD_FLAG(UNIX_SET_GROUP_ID);
+	BIND_BITFIELD_FLAG(UNIX_RESTRICTED_DELETE);
 }

+ 30 - 4
core/io/file_access.h

@@ -60,6 +60,21 @@ public:
 		WRITE_READ = 7,
 	};
 
+	enum UnixPermissionFlags {
+		UNIX_EXECUTE_OTHER = 0x001,
+		UNIX_WRITE_OTHER = 0x002,
+		UNIX_READ_OTHER = 0x004,
+		UNIX_EXECUTE_GROUP = 0x008,
+		UNIX_WRITE_GROUP = 0x010,
+		UNIX_READ_GROUP = 0x020,
+		UNIX_EXECUTE_OWNER = 0x040,
+		UNIX_WRITE_OWNER = 0x080,
+		UNIX_READ_OWNER = 0x100,
+		UNIX_RESTRICTED_DELETE = 0x200,
+		UNIX_SET_GROUP_ID = 0x400,
+		UNIX_SET_USER_ID = 0x800,
+	};
+
 	enum CompressionMode {
 		COMPRESSION_FASTLZ = Compression::MODE_FASTLZ,
 		COMPRESSION_DEFLATE = Compression::MODE_DEFLATE,
@@ -74,8 +89,13 @@ public:
 	bool big_endian = false;
 	bool real_is_double = false;
 
-	virtual uint32_t _get_unix_permissions(const String &p_file) = 0;
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0;
+	virtual BitField<UnixPermissionFlags> _get_unix_permissions(const String &p_file) = 0;
+	virtual Error _set_unix_permissions(const String &p_file, BitField<UnixPermissionFlags> p_permissions) = 0;
+
+	virtual bool _get_hidden_attribute(const String &p_file) = 0;
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) = 0;
+	virtual bool _get_read_only_attribute(const String &p_file) = 0;
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) = 0;
 
 protected:
 	static void _bind_methods();
@@ -185,8 +205,13 @@ public:
 	static CreateFunc get_create_func(AccessType p_access);
 	static bool exists(const String &p_name); ///< return true if a file exists
 	static uint64_t get_modified_time(const String &p_file);
-	static uint32_t get_unix_permissions(const String &p_file);
-	static Error set_unix_permissions(const String &p_file, uint32_t p_permissions);
+	static BitField<FileAccess::UnixPermissionFlags> get_unix_permissions(const String &p_file);
+	static Error set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions);
+
+	static bool get_hidden_attribute(const String &p_file);
+	static Error set_hidden_attribute(const String &p_file, bool p_hidden);
+	static bool get_read_only_attribute(const String &p_file);
+	static Error set_read_only_attribute(const String &p_file, bool p_ro);
 
 	static void set_backup_save(bool p_enable) { backup_save = p_enable; };
 	static bool is_backup_save_enabled() { return backup_save; };
@@ -212,5 +237,6 @@ public:
 
 VARIANT_ENUM_CAST(FileAccess::CompressionMode);
 VARIANT_ENUM_CAST(FileAccess::ModeFlags);
+VARIANT_BITFIELD_CAST(FileAccess::UnixPermissionFlags);
 
 #endif // FILE_ACCESS_H

+ 30 - 2
core/io/file_access_compressed.cpp

@@ -365,20 +365,48 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
 	}
 }
 
-uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) {
+BitField<FileAccess::UnixPermissionFlags> FileAccessCompressed::_get_unix_permissions(const String &p_file) {
 	if (f.is_valid()) {
 		return f->_get_unix_permissions(p_file);
 	}
 	return 0;
 }
 
-Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+Error FileAccessCompressed::_set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) {
 	if (f.is_valid()) {
 		return f->_set_unix_permissions(p_file, p_permissions);
 	}
 	return FAILED;
 }
 
+bool FileAccessCompressed::_get_hidden_attribute(const String &p_file) {
+	if (f.is_valid()) {
+		return f->_get_hidden_attribute(p_file);
+	}
+	return false;
+}
+
+Error FileAccessCompressed::_set_hidden_attribute(const String &p_file, bool p_hidden) {
+	if (f.is_valid()) {
+		return f->_set_hidden_attribute(p_file, p_hidden);
+	}
+	return FAILED;
+}
+
+bool FileAccessCompressed::_get_read_only_attribute(const String &p_file) {
+	if (f.is_valid()) {
+		return f->_get_read_only_attribute(p_file);
+	}
+	return false;
+}
+
+Error FileAccessCompressed::_set_read_only_attribute(const String &p_file, bool p_ro) {
+	if (f.is_valid()) {
+		return f->_set_read_only_attribute(p_file, p_ro);
+	}
+	return FAILED;
+}
+
 void FileAccessCompressed::close() {
 	_close();
 }

+ 7 - 2
core/io/file_access_compressed.h

@@ -94,8 +94,13 @@ public:
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) override;
-	virtual uint32_t _get_unix_permissions(const String &p_file) override;
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
+
+	virtual bool _get_hidden_attribute(const String &p_file) override;
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override;
+	virtual bool _get_read_only_attribute(const String &p_file) override;
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override;
 
 	virtual void close() override;
 

+ 37 - 4
core/io/file_access_encrypted.cpp

@@ -285,13 +285,46 @@ uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
 	return 0;
 }
 
-uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
+BitField<FileAccess::UnixPermissionFlags> FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
+	if (file.is_valid()) {
+		return file->_get_unix_permissions(p_file);
+	}
 	return 0;
 }
 
-Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
-	ERR_PRINT("Setting UNIX permissions on encrypted files is not implemented yet.");
-	return ERR_UNAVAILABLE;
+Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) {
+	if (file.is_valid()) {
+		return file->_set_unix_permissions(p_file, p_permissions);
+	}
+	return FAILED;
+}
+
+bool FileAccessEncrypted::_get_hidden_attribute(const String &p_file) {
+	if (file.is_valid()) {
+		return file->_get_hidden_attribute(p_file);
+	}
+	return false;
+}
+
+Error FileAccessEncrypted::_set_hidden_attribute(const String &p_file, bool p_hidden) {
+	if (file.is_valid()) {
+		return file->_set_hidden_attribute(p_file, p_hidden);
+	}
+	return FAILED;
+}
+
+bool FileAccessEncrypted::_get_read_only_attribute(const String &p_file) {
+	if (file.is_valid()) {
+		return file->_get_read_only_attribute(p_file);
+	}
+	return false;
+}
+
+Error FileAccessEncrypted::_set_read_only_attribute(const String &p_file, bool p_ro) {
+	if (file.is_valid()) {
+		return file->_set_read_only_attribute(p_file, p_ro);
+	}
+	return FAILED;
 }
 
 void FileAccessEncrypted::close() {

+ 7 - 2
core/io/file_access_encrypted.h

@@ -85,8 +85,13 @@ public:
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) override;
-	virtual uint32_t _get_unix_permissions(const String &p_file) override;
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
+
+	virtual bool _get_hidden_attribute(const String &p_file) override;
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override;
+	virtual bool _get_read_only_attribute(const String &p_file) override;
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override;
 
 	virtual void close() override;
 

+ 7 - 2
core/io/file_access_memory.h

@@ -68,8 +68,13 @@ public:
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
-	virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
+
+	virtual bool _get_hidden_attribute(const String &p_file) override { return false; }
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override { return ERR_UNAVAILABLE; }
+	virtual bool _get_read_only_attribute(const String &p_file) override { return false; }
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override { return ERR_UNAVAILABLE; }
 
 	virtual void close() override {}
 

+ 7 - 2
core/io/file_access_pack.h

@@ -150,8 +150,13 @@ class FileAccessPack : public FileAccess {
 	Ref<FileAccess> f;
 	virtual Error open_internal(const String &p_path, int p_mode_flags) override;
 	virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
-	virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
+
+	virtual bool _get_hidden_attribute(const String &p_file) override { return false; }
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override { return ERR_UNAVAILABLE; }
+	virtual bool _get_read_only_attribute(const String &p_file) override { return false; }
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override { return ERR_UNAVAILABLE; }
 
 public:
 	virtual bool is_open() const override;

+ 7 - 2
core/io/file_access_zip.h

@@ -106,8 +106,13 @@ public:
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } // todo
-	virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
+
+	virtual bool _get_hidden_attribute(const String &p_file) override { return false; }
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override { return ERR_UNAVAILABLE; }
+	virtual bool _get_read_only_attribute(const String &p_file) override { return false; }
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override { return ERR_UNAVAILABLE; }
 
 	virtual void close() override;
 

+ 87 - 0
doc/classes/FileAccess.xml

@@ -170,6 +170,14 @@
 				Returns the next 32 bits from the file as a floating-point number.
 			</description>
 		</method>
+		<method name="get_hidden_attribute" qualifiers="static">
+			<return type="bool" />
+			<param index="0" name="file" type="String" />
+			<description>
+				Returns [code]true[/code], if file [code]hidden[/code] attribute is set.
+				[b]Note:[/b] This method is implemented on iOS, BSD, macOS, and Windows.
+			</description>
+		</method>
 		<method name="get_length" qualifiers="const">
 			<return type="int" />
 			<description>
@@ -228,6 +236,14 @@
 				Returns the file cursor's position.
 			</description>
 		</method>
+		<method name="get_read_only_attribute" qualifiers="static">
+			<return type="bool" />
+			<param index="0" name="file" type="String" />
+			<description>
+				Returns [code]true[/code], if file [code]read only[/code] attribute is set.
+				[b]Note:[/b] This method is implemented on iOS, BSD, macOS, and Windows.
+			</description>
+		</method>
 		<method name="get_real" qualifiers="const">
 			<return type="float" />
 			<description>
@@ -241,6 +257,14 @@
 				Returns a SHA-256 [String] representing the file at the given path or an empty [String] on failure.
 			</description>
 		</method>
+		<method name="get_unix_permissions" qualifiers="static">
+			<return type="int" enum="FileAccess.UnixPermissionFlags" is_bitfield="true" />
+			<param index="0" name="file" type="String" />
+			<description>
+				Returns file UNIX permissions.
+				[b]Note:[/b] This method is implemented on iOS, Linux/BSD, and macOS.
+			</description>
+		</method>
 		<method name="get_var" qualifiers="const">
 			<return type="Variant" />
 			<param index="0" name="allow_objects" type="bool" default="false" />
@@ -312,6 +336,33 @@
 				[b]Note:[/b] This is an offset, so you should use negative numbers or the cursor will be at the end of the file.
 			</description>
 		</method>
+		<method name="set_hidden_attribute" qualifiers="static">
+			<return type="int" enum="Error" />
+			<param index="0" name="file" type="String" />
+			<param index="1" name="hidden" type="bool" />
+			<description>
+				Sets file [code]hidden[/code] attribute.
+				[b]Note:[/b] This method is implemented on iOS, BSD, macOS, and Windows.
+			</description>
+		</method>
+		<method name="set_read_only_attribute" qualifiers="static">
+			<return type="int" enum="Error" />
+			<param index="0" name="file" type="String" />
+			<param index="1" name="ro" type="bool" />
+			<description>
+				Sets file [code]read only[/code] attribute.
+				[b]Note:[/b] This method is implemented on iOS, BSD, macOS, and Windows.
+			</description>
+		</method>
+		<method name="set_unix_permissions" qualifiers="static">
+			<return type="int" enum="Error" />
+			<param index="0" name="file" type="String" />
+			<param index="1" name="permissions" type="int" enum="FileAccess.UnixPermissionFlags" is_bitfield="true" />
+			<description>
+				Sets file UNIX permissions.
+				[b]Note:[/b] This method is implemented on iOS, Linux/BSD, and macOS.
+			</description>
+		</method>
 		<method name="store_8">
 			<return type="void" />
 			<param index="0" name="value" type="int" />
@@ -485,5 +536,41 @@
 		<constant name="COMPRESSION_BROTLI" value="4" enum="CompressionMode">
 			Uses the [url=https://github.com/google/brotli]brotli[/url] compression method (only decompression is supported).
 		</constant>
+		<constant name="UNIX_READ_OWNER" value="256" enum="UnixPermissionFlags" is_bitfield="true">
+			Read for owner bit.
+		</constant>
+		<constant name="UNIX_WRITE_OWNER" value="128" enum="UnixPermissionFlags" is_bitfield="true">
+			Write for owner bit.
+		</constant>
+		<constant name="UNIX_EXECUTE_OWNER" value="64" enum="UnixPermissionFlags" is_bitfield="true">
+			Execute for owner bit.
+		</constant>
+		<constant name="UNIX_READ_GROUP" value="32" enum="UnixPermissionFlags" is_bitfield="true">
+			Read for group bit.
+		</constant>
+		<constant name="UNIX_WRITE_GROUP" value="16" enum="UnixPermissionFlags" is_bitfield="true">
+			Write for group bit.
+		</constant>
+		<constant name="UNIX_EXECUTE_GROUP" value="8" enum="UnixPermissionFlags" is_bitfield="true">
+			Execute for group bit.
+		</constant>
+		<constant name="UNIX_READ_OTHER" value="4" enum="UnixPermissionFlags" is_bitfield="true">
+			Read for other bit.
+		</constant>
+		<constant name="UNIX_WRITE_OTHER" value="2" enum="UnixPermissionFlags" is_bitfield="true">
+			Write for other bit.
+		</constant>
+		<constant name="UNIX_EXECUTE_OTHER" value="1" enum="UnixPermissionFlags" is_bitfield="true">
+			Execute for other bit.
+		</constant>
+		<constant name="UNIX_SET_USER_ID" value="2048" enum="UnixPermissionFlags" is_bitfield="true">
+			Set user id on execution bit.
+		</constant>
+		<constant name="UNIX_SET_GROUP_ID" value="1024" enum="UnixPermissionFlags" is_bitfield="true">
+			Set group id on execution bit.
+		</constant>
+		<constant name="UNIX_RESTRICTED_DELETE" value="512" enum="UnixPermissionFlags" is_bitfield="true">
+			Restricted deletion (sticky) bit.
+		</constant>
 	</constants>
 </class>

+ 71 - 3
drivers/unix/file_access_unix.cpp

@@ -313,19 +313,19 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
 	}
 }
 
-uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
+BitField<FileAccess::UnixPermissionFlags> FileAccessUnix::_get_unix_permissions(const String &p_file) {
 	String file = fix_path(p_file);
 	struct stat status = {};
 	int err = stat(file.utf8().get_data(), &status);
 
 	if (!err) {
-		return status.st_mode & 0x7FF; //only permissions
+		return status.st_mode & 0xFFF; //only permissions
 	} else {
 		ERR_FAIL_V_MSG(0, "Failed to get unix permissions for: " + p_file + ".");
 	}
 }
 
-Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+Error FileAccessUnix::_set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) {
 	String file = fix_path(p_file);
 
 	int err = chmod(file.utf8().get_data(), p_permissions);
@@ -336,6 +336,74 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per
 	return FAILED;
 }
 
+bool FileAccessUnix::_get_hidden_attribute(const String &p_file) {
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+	String file = fix_path(p_file);
+
+	struct stat st = {};
+	int err = stat(file.utf8().get_data(), &st);
+	ERR_FAIL_COND_V_MSG(err, false, "Failed to get attributes for: " + p_file);
+
+	return (st.st_flags & UF_HIDDEN);
+#else
+	return false;
+#endif
+}
+
+Error FileAccessUnix::_set_hidden_attribute(const String &p_file, bool p_hidden) {
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+	String file = fix_path(p_file);
+
+	struct stat st = {};
+	int err = stat(file.utf8().get_data(), &st);
+	ERR_FAIL_COND_V_MSG(err, FAILED, "Failed to get attributes for: " + p_file);
+
+	if (p_hidden) {
+		err = chflags(file.utf8().get_data(), st.st_flags | UF_HIDDEN);
+	} else {
+		err = chflags(file.utf8().get_data(), st.st_flags & ~UF_HIDDEN);
+	}
+	ERR_FAIL_COND_V_MSG(err, FAILED, "Failed to set attributes for: " + p_file);
+	return OK;
+#else
+	return ERR_UNAVAILABLE;
+#endif
+}
+
+bool FileAccessUnix::_get_read_only_attribute(const String &p_file) {
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+	String file = fix_path(p_file);
+
+	struct stat st = {};
+	int err = stat(file.utf8().get_data(), &st);
+	ERR_FAIL_COND_V_MSG(err, false, "Failed to get attributes for: " + p_file);
+
+	return st.st_flags & UF_IMMUTABLE;
+#else
+	return false;
+#endif
+}
+
+Error FileAccessUnix::_set_read_only_attribute(const String &p_file, bool p_ro) {
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+	String file = fix_path(p_file);
+
+	struct stat st = {};
+	int err = stat(file.utf8().get_data(), &st);
+	ERR_FAIL_COND_V_MSG(err, FAILED, "Failed to get attributes for: " + p_file);
+
+	if (p_ro) {
+		err = chflags(file.utf8().get_data(), st.st_flags | UF_IMMUTABLE);
+	} else {
+		err = chflags(file.utf8().get_data(), st.st_flags & ~UF_IMMUTABLE);
+	}
+	ERR_FAIL_COND_V_MSG(err, FAILED, "Failed to set attributes for: " + p_file);
+	return OK;
+#else
+	return ERR_UNAVAILABLE;
+#endif
+}
+
 void FileAccessUnix::close() {
 	_close();
 }

+ 7 - 2
drivers/unix/file_access_unix.h

@@ -79,8 +79,13 @@ public:
 	virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) override;
-	virtual uint32_t _get_unix_permissions(const String &p_file) override;
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
+
+	virtual bool _get_hidden_attribute(const String &p_file) override;
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override;
+	virtual bool _get_read_only_attribute(const String &p_file) override;
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override;
 
 	virtual void close() override;
 

+ 50 - 2
drivers/windows/file_access_windows.cpp

@@ -381,14 +381,62 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
 	}
 }
 
-uint32_t FileAccessWindows::_get_unix_permissions(const String &p_file) {
+BitField<FileAccess::UnixPermissionFlags> FileAccessWindows::_get_unix_permissions(const String &p_file) {
 	return 0;
 }
 
-Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+Error FileAccessWindows::_set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) {
 	return ERR_UNAVAILABLE;
 }
 
+bool FileAccessWindows::_get_hidden_attribute(const String &p_file) {
+	String file = fix_path(p_file);
+
+	DWORD attrib = GetFileAttributesW((LPCWSTR)file.utf16().get_data());
+	ERR_FAIL_COND_V_MSG(attrib == INVALID_FILE_ATTRIBUTES, false, "Failed to get attributes for: " + p_file);
+	return (attrib & FILE_ATTRIBUTE_HIDDEN);
+}
+
+Error FileAccessWindows::_set_hidden_attribute(const String &p_file, bool p_hidden) {
+	String file = fix_path(p_file);
+
+	DWORD attrib = GetFileAttributesW((LPCWSTR)file.utf16().get_data());
+	ERR_FAIL_COND_V_MSG(attrib == INVALID_FILE_ATTRIBUTES, FAILED, "Failed to get attributes for: " + p_file);
+	BOOL ok;
+	if (p_hidden) {
+		ok = SetFileAttributesW((LPCWSTR)file.utf16().get_data(), attrib | FILE_ATTRIBUTE_HIDDEN);
+	} else {
+		ok = SetFileAttributesW((LPCWSTR)file.utf16().get_data(), attrib & ~FILE_ATTRIBUTE_HIDDEN);
+	}
+	ERR_FAIL_COND_V_MSG(!ok, FAILED, "Failed to set attributes for: " + p_file);
+
+	return OK;
+}
+
+bool FileAccessWindows::_get_read_only_attribute(const String &p_file) {
+	String file = fix_path(p_file);
+
+	DWORD attrib = GetFileAttributesW((LPCWSTR)file.utf16().get_data());
+	ERR_FAIL_COND_V_MSG(attrib == INVALID_FILE_ATTRIBUTES, false, "Failed to get attributes for: " + p_file);
+	return (attrib & FILE_ATTRIBUTE_READONLY);
+}
+
+Error FileAccessWindows::_set_read_only_attribute(const String &p_file, bool p_ro) {
+	String file = fix_path(p_file);
+
+	DWORD attrib = GetFileAttributesW((LPCWSTR)file.utf16().get_data());
+	ERR_FAIL_COND_V_MSG(attrib == INVALID_FILE_ATTRIBUTES, FAILED, "Failed to get attributes for: " + p_file);
+	BOOL ok;
+	if (p_ro) {
+		ok = SetFileAttributesW((LPCWSTR)file.utf16().get_data(), attrib | FILE_ATTRIBUTE_READONLY);
+	} else {
+		ok = SetFileAttributesW((LPCWSTR)file.utf16().get_data(), attrib & ~FILE_ATTRIBUTE_READONLY);
+	}
+	ERR_FAIL_COND_V_MSG(!ok, FAILED, "Failed to set attributes for: " + p_file);
+
+	return OK;
+}
+
 void FileAccessWindows::close() {
 	_close();
 }

+ 7 - 2
drivers/windows/file_access_windows.h

@@ -80,8 +80,13 @@ public:
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 	uint64_t _get_modified_time(const String &p_file) override;
-	virtual uint32_t _get_unix_permissions(const String &p_file) override;
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
+
+	virtual bool _get_hidden_attribute(const String &p_file) override;
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override;
+	virtual bool _get_read_only_attribute(const String &p_file) override;
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override;
 
 	virtual void close() override;
 

+ 7 - 2
platform/android/file_access_android.h

@@ -76,8 +76,13 @@ public:
 	virtual bool file_exists(const String &p_path) override; // return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
-	virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
+
+	virtual bool _get_hidden_attribute(const String &p_file) override { return false; }
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override { return ERR_UNAVAILABLE; }
+	virtual bool _get_read_only_attribute(const String &p_file) override { return false; }
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override { return ERR_UNAVAILABLE; }
 
 	virtual void close() override;
 

+ 7 - 2
platform/android/file_access_filesystem_jandroid.h

@@ -91,8 +91,13 @@ public:
 	static void setup(jobject p_file_access_handler);
 
 	virtual uint64_t _get_modified_time(const String &p_file) override;
-	virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
-	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+	virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
+
+	virtual bool _get_hidden_attribute(const String &p_file) override { return false; }
+	virtual Error _set_hidden_attribute(const String &p_file, bool p_hidden) override { return ERR_UNAVAILABLE; }
+	virtual bool _get_read_only_attribute(const String &p_file) override { return false; }
+	virtual Error _set_read_only_attribute(const String &p_file, bool p_ro) override { return ERR_UNAVAILABLE; }
 
 	virtual void close() override;