Browse Source

Add FileAccess::set_unix_permissions for Unix platforms

Juan Linietsky 6 years ago
parent
commit
cd4449e7ab

+ 8 - 0
core/io/file_access_buffered_fa.h

@@ -143,6 +143,14 @@ public:
 		return f._get_modified_time(p_file);
 	}
 
+	virtual uint32_t _get_unix_permissions(const String &p_file) {
+		return f._get_unix_permissions(p_file);
+	}
+
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+		return f._set_unix_permissions(p_file, p_permissions);
+	}
+
 	FileAccessBufferedFA(){
 
 	};

+ 13 - 0
core/io/file_access_compressed.cpp

@@ -373,6 +373,19 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
 		return 0;
 }
 
+uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) {
+	if (f)
+		return f->_get_unix_permissions(p_file);
+	return 0;
+}
+
+Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+	if (f) {
+		return f->_set_unix_permissions(p_file, p_permissions);
+	}
+	return FAILED;
+}
+
 FileAccessCompressed::FileAccessCompressed() :
 		cmode(Compression::MODE_ZSTD),
 		writing(false),

+ 2 - 0
core/io/file_access_compressed.h

@@ -91,6 +91,8 @@ public:
 	virtual bool file_exists(const String &p_name); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file);
+	virtual uint32_t _get_unix_permissions(const String &p_file);
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
 
 	FileAccessCompressed();
 	virtual ~FileAccessCompressed();

+ 10 - 0
core/io/file_access_encrypted.cpp

@@ -301,6 +301,16 @@ uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
 	return 0;
 }
 
+uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
+
+	return 0;
+}
+
+Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+	return FAILED;
+}
+
 FileAccessEncrypted::FileAccessEncrypted() {
 
 	file = NULL;

+ 2 - 0
core/io/file_access_encrypted.h

@@ -79,6 +79,8 @@ public:
 	virtual bool file_exists(const String &p_name); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file);
+	virtual uint32_t _get_unix_permissions(const String &p_file);
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
 
 	FileAccessEncrypted();
 	~FileAccessEncrypted();

+ 2 - 0
core/io/file_access_memory.h

@@ -70,6 +70,8 @@ public:
 	virtual bool file_exists(const String &p_name); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+	virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
 
 	FileAccessMemory();
 };

+ 10 - 0
core/io/file_access_network.cpp

@@ -497,6 +497,16 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
 	return exists_modtime;
 }
 
+uint32_t FileAccessNetwork::_get_unix_permissions(const String &p_file) {
+	//could be implemented, not sure if worth it
+	return 0;
+}
+
+Error FileAccessNetwork::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+	return FAILED;
+}
+
 void FileAccessNetwork::configure() {
 
 	GLOBAL_DEF("network/remote_fs/page_size", 65536);

+ 2 - 0
core/io/file_access_network.h

@@ -159,6 +159,8 @@ public:
 	virtual bool file_exists(const String &p_path); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file);
+	virtual uint32_t _get_unix_permissions(const String &p_file);
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
 
 	static void configure();
 

+ 2 - 0
core/io/file_access_pack.h

@@ -142,6 +142,8 @@ class FileAccessPack : public FileAccess {
 	FileAccess *f;
 	virtual Error _open(const String &p_path, int p_mode_flags);
 	virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+	virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
 
 public:
 	virtual void close();

+ 2 - 0
core/io/file_access_zip.h

@@ -112,6 +112,8 @@ public:
 	virtual bool file_exists(const String &p_name); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
+	virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
 
 	FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
 	~FileAccessZip();

+ 1 - 1
core/os/dir_access.cpp

@@ -330,7 +330,7 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
 
 	if (err == OK && p_chmod_flags != -1) {
 		fdst->close();
-		err = fdst->_chmod(p_to, p_chmod_flags);
+		err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
 		// If running on a platform with no chmod support (i.e., Windows), don't fail
 		if (err == ERR_UNAVAILABLE)
 			err = OK;

+ 23 - 0
core/os/file_access.cpp

@@ -507,6 +507,29 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
 	return mt;
 }
 
+uint32_t FileAccess::get_unix_permissions(const String &p_file) {
+
+	if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file))
+		return 0;
+
+	FileAccess *fa = create_for_path(p_file);
+	ERR_FAIL_COND_V(!fa, 0);
+
+	uint32_t mt = fa->_get_unix_permissions(p_file);
+	memdelete(fa);
+	return mt;
+}
+
+Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+	FileAccess *fa = create_for_path(p_file);
+	ERR_FAIL_COND_V(!fa, ERR_CANT_CREATE);
+
+	Error err = fa->_set_unix_permissions(p_file, p_permissions);
+	memdelete(fa);
+	return err;
+}
+
 void FileAccess::store_string(const String &p_string) {
 
 	if (p_string.length() == 0)

+ 5 - 2
core/os/file_access.h

@@ -56,6 +56,9 @@ public:
 	bool endian_swap;
 	bool real_is_double;
 
+	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;
+
 protected:
 	String fix_path(const String &p_path) const;
 	virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file
@@ -148,14 +151,14 @@ public:
 
 	virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
 
-	virtual Error _chmod(const String &p_path, int p_mod) { return ERR_UNAVAILABLE; }
-
 	static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
 	static FileAccess *create_for_path(const String &p_path);
 	static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files.
 	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 void set_backup_save(bool p_enable) { backup_save = p_enable; };
 	static bool is_backup_save_enabled() { return backup_save; };

+ 3 - 1
core/os/os.h

@@ -45,6 +45,8 @@
 	@author Juan Linietsky <[email protected]>
 */
 
+class Mutex;
+
 class OS {
 
 	static OS *singleton;
@@ -260,7 +262,7 @@ public:
 	virtual int get_low_processor_usage_mode_sleep_usec() const;
 
 	virtual String get_executable_path() const;
-	virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
+	virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL) = 0;
 	virtual Error kill(const ProcessID &p_pid) = 0;
 	virtual int get_process_id() const;
 

+ 19 - 2
drivers/unix/file_access_unix.cpp

@@ -293,8 +293,25 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
 	};
 }
 
-Error FileAccessUnix::_chmod(const String &p_path, int p_mod) {
-	int err = chmod(p_path.utf8().get_data(), p_mod);
+uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
+
+	String file = fix_path(p_file);
+	struct stat flags;
+	int err = stat(file.utf8().get_data(), &flags);
+
+	if (!err) {
+		return flags.st_mode & 0x7FF; //only permissions
+	} else {
+		ERR_EXPLAIN("Failed to get unix permissions for: " + p_file);
+		ERR_FAIL_V(0);
+	};
+}
+
+Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+	String file = fix_path(p_file);
+
+	int err = chmod(file.utf8().get_data(), p_permissions);
 	if (!err) {
 		return OK;
 	}

+ 2 - 2
drivers/unix/file_access_unix.h

@@ -85,8 +85,8 @@ public:
 	virtual bool file_exists(const String &p_path); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file);
-
-	virtual Error _chmod(const String &p_path, int p_mod);
+	virtual uint32_t _get_unix_permissions(const String &p_file);
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
 
 	FileAccessUnix();
 	virtual ~FileAccessUnix();

+ 16 - 2
drivers/unix/os_unix.cpp

@@ -276,7 +276,7 @@ uint64_t OS_Unix::get_ticks_usec() const {
 	return longtime;
 }
 
-Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
+Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
 
 #ifdef __EMSCRIPTEN__
 	// Don't compile this code at all to avoid undefined references.
@@ -303,11 +303,17 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
 		ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
 
 		char buf[65535];
+
 		while (fgets(buf, 65535, f)) {
 
+			if (p_pipe_mutex) {
+				p_pipe_mutex->lock();
+			}
 			(*r_pipe) += buf;
+			if (p_pipe_mutex) {
+				p_pipe_mutex->unlock();
+			}
 		}
-
 		int rv = pclose(f);
 		if (r_exitcode)
 			*r_exitcode = rv;
@@ -320,6 +326,13 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
 
 	if (pid == 0) {
 		// is child
+
+		if (!p_blocking) {
+			// For non blocking calls, create a new session-ID so parent won't wait for it.
+			// This ensures the process won't go zombie at end.
+			setsid();
+		}
+
 		Vector<CharString> cs;
 		cs.push_back(p_path.utf8());
 		for (int i = 0; i < p_arguments.size(); i++)
@@ -342,6 +355,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
 		waitpid(pid, &status, 0);
 		if (r_exitcode)
 			*r_exitcode = WEXITSTATUS(status);
+
 	} else {
 
 		if (r_child_id)

+ 1 - 1
drivers/unix/os_unix.h

@@ -89,7 +89,7 @@ public:
 	virtual void delay_usec(uint32_t p_usec) const;
 	virtual uint64_t get_ticks_usec() const;
 
-	virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
+	virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
 	virtual Error kill(const ProcessID &p_pid);
 	virtual int get_process_id() const;
 

+ 10 - 0
drivers/windows/file_access_windows.cpp

@@ -339,6 +339,16 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
 	}
 }
 
+uint32_t FileAccessWindows::_get_unix_permissions(const String &p_file) {
+	ERR_PRINT("Windows does not support unix permissions");
+	return 0;
+}
+
+Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+	ERR_PRINT("Windows does not support unix permissions");
+	return FAILED;
+}
+
 FileAccessWindows::FileAccessWindows() :
 		f(NULL),
 		flags(0),

+ 2 - 0
drivers/windows/file_access_windows.h

@@ -80,6 +80,8 @@ public:
 	virtual bool file_exists(const String &p_name); ///< return true if a file exists
 
 	uint64_t _get_modified_time(const String &p_file);
+	virtual uint32_t _get_unix_permissions(const String &p_file);
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
 
 	FileAccessWindows();
 	virtual ~FileAccessWindows();

+ 2 - 0
platform/android/file_access_android.h

@@ -70,6 +70,8 @@ public:
 	virtual bool file_exists(const String &p_path); ///< return true if a file exists
 
 	virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+	virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
 
 	//static void make_default();
 

+ 2 - 0
platform/android/file_access_jandroid.h

@@ -74,6 +74,8 @@ public:
 	static void setup(jobject p_io);
 
 	virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+	virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+	virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
 
 	FileAccessJAndroid();
 	~FileAccessJAndroid();

+ 1 - 1
platform/osx/export/export.cpp

@@ -568,7 +568,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 					f->close();
 					if (is_execute) {
 						// Chmod with 0755 if the file is executable
-						f->_chmod(file, 0755);
+						FileAccess::set_unix_permissions(file, 0755);
 					}
 					memdelete(f);
 				} else {