os: add is_executable, is_writable and is_readable
							parent
							
								
									126289c19b
								
							
						
					
					
						commit
						025efcb731
					
				
							
								
								
									
										47
									
								
								vlib/os/os.v
								
								
								
								
							
							
						
						
									
										47
									
								
								vlib/os/os.v
								
								
								
								
							|  | @ -505,16 +505,59 @@ pub fn unsetenv(name string) int { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	F_OK = 0 | ||||
| 	X_OK = 1 | ||||
| 	W_OK = 2 | ||||
| 	R_OK = 4 | ||||
| ) | ||||
| 
 | ||||
| // exists returns true if `path` exists.
 | ||||
| pub fn exists(path string) bool { | ||||
| 	$if windows { | ||||
| 		p := path.replace('/', '\\') | ||||
| 		return C._waccess(p.to_wide(), 0) != -1 | ||||
| 		return C._waccess(p.to_wide(), F_OK) != -1 | ||||
| 	} $else { | ||||
| 		return C.access(path.str, 0) != -1 | ||||
| 		return C.access(path.str, F_OK) != -1 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // `is_executable` returns `true` if `path` is executable.
 | ||||
| pub fn is_executable(path string) bool { | ||||
|   $if windows { | ||||
|     // NB: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess?view=vs-2019
 | ||||
|     // i.e. there is no X bit there, the modes can be:
 | ||||
|     // 00 Existence only
 | ||||
|     // 02 Write-only
 | ||||
|     // 04 Read-only
 | ||||
|     // 06 Read and write
 | ||||
|     p := os.realpath( path ) | ||||
|     return ( os.exists( p ) && p.ends_with('.exe') ) | ||||
|   } $else { | ||||
|     return C.access(path.str, X_OK) != -1 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // `is_writable` returns `true` if `path` is writable.
 | ||||
| pub fn is_writable(path string) bool { | ||||
|   $if windows { | ||||
|     p := path.replace('/', '\\') | ||||
|     return C._waccess(p.to_wide(), W_OK) != -1 | ||||
|   } $else { | ||||
|     return C.access(path.str, W_OK) != -1 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // `is_readable` returns `true` if `path` is readable.
 | ||||
| pub fn is_readable(path string) bool { | ||||
|   $if windows { | ||||
|     p := path.replace('/', '\\') | ||||
|     return C._waccess(p.to_wide(), R_OK) != -1 | ||||
|   } $else { | ||||
|     return C.access(path.str, R_OK) != -1 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| [deprecated] | ||||
| pub fn file_exists(_path string) bool { | ||||
| 	panic('use os.exists(path) instead of os.file_exists(path)') | ||||
|  |  | |||
|  | @ -107,7 +107,7 @@ fn test_walk() { | |||
|     os.write_file(file1,'test-1') | ||||
| 
 | ||||
|     os.walk(folder, walk_callback) | ||||
| 	 | ||||
| 
 | ||||
| 	os.rm(file1) | ||||
| 	os.rmdir(folder) | ||||
| } | ||||
|  | @ -150,17 +150,17 @@ fn test_tmpdir(){ | |||
| 	t := os.tmpdir() | ||||
| 	assert t.len > 0 | ||||
| 	assert os.is_dir(t) | ||||
| 	 | ||||
| 
 | ||||
| 	tfile := t + os.path_separator + 'tmpfile.txt' | ||||
| 	 | ||||
| 
 | ||||
| 	os.rm(tfile) // just in case
 | ||||
| 	 | ||||
| 
 | ||||
| 	tfile_content := 'this is a temporary file' | ||||
| 	os.write_file(tfile, tfile_content) | ||||
| 	 | ||||
| 
 | ||||
| 	tfile_content_read := os.read_file(tfile) or { panic(err) } | ||||
| 	assert tfile_content_read == tfile_content | ||||
| 	 | ||||
| 
 | ||||
| 	os.rm(tfile) | ||||
| } | ||||
| 
 | ||||
|  | @ -175,7 +175,7 @@ fn test_make_symlink_check_is_link_and_remove_symlink() { | |||
|    folder  := 'tfolder' | ||||
|    symlink := 'tsymlink' | ||||
| 
 | ||||
|    os.rm(symlink)  | ||||
|    os.rm(symlink) | ||||
|    os.rm(folder) | ||||
| 
 | ||||
|    os.mkdir(folder) or { panic(err) } | ||||
|  | @ -185,12 +185,12 @@ fn test_make_symlink_check_is_link_and_remove_symlink() { | |||
|    os.system('ln -s $folder $symlink') | ||||
|    assert os.is_link(symlink) == true | ||||
| 
 | ||||
|    os.rm(symlink)  | ||||
|    os.rm(symlink) | ||||
|    os.rm(folder) | ||||
|     | ||||
| 
 | ||||
|    folder_exists := os.is_dir(folder) | ||||
|    assert folder_exists == false | ||||
|     | ||||
| 
 | ||||
|    symlink_exists := os.is_link(symlink) | ||||
|    assert symlink_exists == false | ||||
| } | ||||
|  | @ -234,6 +234,32 @@ fn test_symlink() { | |||
|   os.rm('symlink2') | ||||
| } | ||||
| 
 | ||||
| fn test_is_executable_writable_readable() { | ||||
|   file_name := os.tmpdir() + os.path_separator + 'rwxfile.exe' | ||||
| 
 | ||||
|   mut f := os.create(file_name) or { | ||||
|     eprintln('failed to create file $file_name') | ||||
|     return | ||||
|   } | ||||
|   f.close() | ||||
|    | ||||
|   $if !windows { | ||||
|     os.chmod(file_name, 0600) // mark as readable && writable, but NOT executable  
 | ||||
|     assert os.is_writable(file_name) | ||||
|     assert os.is_readable(file_name) | ||||
|     assert !os.is_executable(file_name)   | ||||
|     os.chmod(file_name, 0700) // mark as executable too
 | ||||
|     assert os.is_executable(file_name) | ||||
|   } $else { | ||||
|     assert os.is_writable(file_name) | ||||
|     assert os.is_readable(file_name) | ||||
|     assert os.is_executable(file_name)     | ||||
|   } | ||||
| 
 | ||||
|   // We finally delete the test file.
 | ||||
|   os.rm(file_name) | ||||
| } | ||||
| 
 | ||||
| // this function is called by both test_aaa_setup & test_zzz_cleanup
 | ||||
| // it ensures that os tests do not polute the filesystem with leftover
 | ||||
| // files so that they can be run several times in a row.
 | ||||
|  | @ -241,7 +267,7 @@ fn cleanup_leftovers(){ | |||
| 	// possible leftovers from test_cp
 | ||||
| 	os.rm('cp_example.txt') | ||||
| 	os.rm('cp_new_example.txt') | ||||
| 	 | ||||
| 
 | ||||
| 	// possible leftovers from test_cp_r
 | ||||
| 	os.rm('ex/ex2/ex2.txt') | ||||
| 	os.rmdir('ex/ex2') | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue