Skip to content

Commit fc75b64

Browse files
committed
Support for querying/setting UNIX file permissions
To be used in the feature branch xolox/vim-easytags#async-take-two of the vim-easytags plug-in (see also xolox/vim-easytags#84) in order to preserve the permissions of tags files (as explained in the docs; it's a good example of why this functionality is very useful to have on UNIX).
1 parent 81fdec8 commit fc75b64

File tree

4 files changed

+146
-13
lines changed

4 files changed

+146
-13
lines changed

README.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ from the source code of the miscellaneous scripts using the Python module
3737

3838
<!-- Start of generated documentation -->
3939

40-
The documentation of the 89 functions below was extracted from
41-
18 Vim scripts on June 22, 2014 at 02:54.
40+
The documentation of the 91 functions below was extracted from
41+
19 Vim scripts on June 29, 2014 at 23:33.
4242

4343
### Asynchronous Vim script evaluation
4444

@@ -634,6 +634,41 @@ relative, false (0) otherwise.
634634

635635
Create a temporary directory and return the pathname of the directory.
636636

637+
### Manipulation of UNIX file permissions
638+
639+
Vim's [writefile()][] function cannot set file permissions for newly created
640+
files and although Vim script has a function to get file permissions (see
641+
[getfperm()][]) there is no equivalent for changing a file's permissions.
642+
643+
This omission breaks the otherwise very useful idiom of updating a file by
644+
writing its new contents to a temporary file and then renaming the temporary
645+
file into place (which is as close as you're going to get to atomically
646+
updating a file's contents on UNIX) because the file's permissions will not
647+
be preserved!
648+
649+
**Here's a practical example:** My [vim-easytags][] plug-in writes tags file
650+
updates to a temporary file and renames the temporary file into place. When
651+
I use `sudo -s` on Ubuntu Linux it preserves my environment variables so my
652+
`~/.vimrc` and the [vim-easytags][] plug-in are still loaded. Now when a
653+
tags file is written the file becomes owned by root (my effective user id in
654+
the `sudo` session). Once I leave the `sudo` session I can no longer update
655+
my tags file because it's now owned by root … ಠ_ಠ
656+
657+
[getfperm()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#getfperm()
658+
[vim-easytags]: http://peterodding.com/code/vim/easytags/
659+
[writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile()
660+
661+
#### The `xolox#misc#perm#get()` function
662+
663+
Get the permissions of the pathname given as the first argument. Returns a
664+
string which you can later pass to `xolox#misc#perm#set()`.
665+
666+
#### The `xolox#misc#perm#set()` function
667+
668+
Set the permissions (the second argument) of the pathname given as the
669+
first argument. Expects a permissions string created by
670+
`xolox#misc#perm#get()`.
671+
637672
### Persist/recall Vim values from/to files
638673

639674
Vim's [string()][] function can be used to serialize Vim script values like

autoload/xolox/misc.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
" The version of my miscellaneous scripts.
22
"
33
" Author: Peter Odding <[email protected]>
4-
" Last Change: June 22, 2014
4+
" Last Change: June 29, 2014
55
" URL: http://peterodding.com/code/vim/misc/
66

7-
let g:xolox#misc#version = '1.11'
7+
let g:xolox#misc#version = '1.12'

autoload/xolox/misc/perm.vim

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
" Manipulation of UNIX file permissions.
2+
"
3+
" Author: Peter Odding <[email protected]>
4+
" Last Change: June 29, 2014
5+
" URL: http://peterodding.com/code/vim/misc/
6+
"
7+
" Vim's [writefile()][] function cannot set file permissions for newly created
8+
" files and although Vim script has a function to get file permissions (see
9+
" [getfperm()][]) there is no equivalent for changing a file's permissions.
10+
"
11+
" This omission breaks the otherwise very useful idiom of updating a file by
12+
" writing its new contents to a temporary file and then renaming the temporary
13+
" file into place (which is as close as you're going to get to atomically
14+
" updating a file's contents on UNIX) because the file's permissions will not
15+
" be preserved!
16+
"
17+
" **Here's a practical example:** My [vim-easytags][] plug-in writes tags file
18+
" updates to a temporary file and renames the temporary file into place. When
19+
" I use `sudo -s` on Ubuntu Linux it preserves my environment variables so my
20+
" `~/.vimrc` and the [vim-easytags][] plug-in are still loaded. Now when a
21+
" tags file is written the file becomes owned by root (my effective user id in
22+
" the `sudo` session). Once I leave the `sudo` session I can no longer update
23+
" my tags file because it's now owned by root … ಠ_ಠ
24+
"
25+
" [getfperm()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#getfperm()
26+
" [vim-easytags]: http://peterodding.com/code/vim/easytags/
27+
" [writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile()
28+
29+
function! xolox#misc#perm#get(fname)
30+
" Get the permissions of the pathname given as the first argument. Returns a
31+
" string which you can later pass to `xolox#misc#perm#set()`.
32+
let pathname = xolox#misc#path#absolute(a:fname)
33+
if filereadable(pathname)
34+
let command = printf('stat --format %%a %s', shellescape(pathname))
35+
let result = xolox#misc#os#exec({'command': command})
36+
if result['exit_code'] == 0 && len(result['stdout']) >= 1
37+
let permissions_string = '0' . xolox#misc#str#trim(result['stdout'][0])
38+
if permissions_string =~ '^[0-7]\+$'
39+
call xolox#misc#msg#debug("vim-misc %s: Found permissions of %s: %s.", g:xolox#misc#version, pathname, permissions_string)
40+
return permissions_string
41+
endif
42+
endif
43+
endif
44+
return ''
45+
endfunction
46+
47+
function! xolox#misc#perm#set(fname, perms)
48+
" Set the permissions (the second argument) of the pathname given as the
49+
" first argument. Expects a permissions string created by
50+
" `xolox#misc#perm#get()`.
51+
if !empty(a:perms)
52+
let pathname = xolox#misc#path#absolute(a:fname)
53+
let command = printf('chmod %s %s', shellescape(a:perms), shellescape(pathname))
54+
let result = xolox#misc#os#exec({'command': command})
55+
if result['exit_code'] == 0
56+
call xolox#misc#msg#debug("vim-misc %s: Successfully set permissions of %s to %s.", g:xolox#misc#version, pathname, a:perms)
57+
return 1
58+
endif
59+
endif
60+
return 0
61+
endfunction

doc/misc.txt

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,20 @@ Contents ~
6464
10. The |xolox#misc#path#decode()| function
6565
11. The |xolox#misc#path#is_relative()| function
6666
12. The |xolox#misc#path#tempdir()| function
67-
13. Persist/recall Vim values from/to files |misc-persist-recall-vim-values-from-to-files|
67+
13. Manipulation of UNIX file permissions |misc-manipulation-of-unix-file-permissions|
68+
1. The |xolox#misc#perm#get()| function
69+
2. The |xolox#misc#perm#set()| function
70+
14. Persist/recall Vim values from/to files |misc-persist-recall-vim-values-from-to-files|
6871
1. The |xolox#misc#persist#load()| function
6972
2. The |xolox#misc#persist#save()| function
70-
14. String handling |misc-string-handling|
73+
15. String handling |misc-string-handling|
7174
1. The |xolox#misc#str#slug()| function
7275
2. The |xolox#misc#str#ucfirst()| function
7376
3. The |xolox#misc#str#compact()| function
7477
4. The |xolox#misc#str#trim()| function
7578
5. The |xolox#misc#str#indent()| function
7679
6. The |xolox#misc#str#dedent()| function
77-
15. Test runner & infrastructure for Vim plug-ins |misc-test-runner-infrastructure-for-vim-plug-ins|
80+
16. Test runner & infrastructure for Vim plug-ins |misc-test-runner-infrastructure-for-vim-plug-ins|
7881
1. The |xolox#misc#test#reset()| function
7982
2. The |xolox#misc#test#summarize()| function
8083
3. The |xolox#misc#test#wrap()| function
@@ -83,7 +86,7 @@ Contents ~
8386
6. The |xolox#misc#test#assert_true()| function
8487
7. The |xolox#misc#test#assert_equals()| function
8588
8. The |xolox#misc#test#assert_same_type()| function
86-
16. Tests for the miscellaneous Vim scripts |tests-for-miscellaneous-vim-scripts|
89+
17. Tests for the miscellaneous Vim scripts |tests-for-miscellaneous-vim-scripts|
8790
1. The |xolox#misc#tests#run()| function
8891
2. The |xolox#misc#tests#pattern_escaping()| function
8992
3. The |xolox#misc#tests#substitute_escaping()| function
@@ -107,12 +110,12 @@ function
107110
19. The |xolox#misc#tests#multiline_string_dedent()| function
108111
20. The |xolox#misc#tests#version_string_parsing()| function
109112
21. The |xolox#misc#tests#version_string_comparison()| function
110-
17. Timing of long during operations |misc-timing-of-long-during-operations|
113+
18. Timing of long during operations |misc-timing-of-long-during-operations|
111114
1. The |xolox#misc#timer#start()| function
112115
2. The |xolox#misc#timer#stop()| function
113116
3. The |xolox#misc#timer#force()| function
114117
4. The |xolox#misc#timer#convert()| function
115-
18. Version string handling |misc-version-string-handling|
118+
19. Version string handling |misc-version-string-handling|
116119
1. The |xolox#misc#version#parse()| function
117120
2. The |xolox#misc#version#at_least()| function
118121
4. Contact |misc-contact|
@@ -162,8 +165,8 @@ For those who are curious: The function descriptions given below were extracted
162165
from the source code of the miscellaneous scripts using the Python module
163166
'vimdoctool.py' included in vim-tools [5].
164167

165-
The documentation of the 89 functions below was extracted from 18 Vim scripts
166-
on June 22, 2014 at 02:54.
168+
The documentation of the 91 functions below was extracted from 19 Vim scripts
169+
on June 29, 2014 at 23:33.
167170

168171
-------------------------------------------------------------------------------
169172
*misc-asynchronous-vim-script-evaluation*
@@ -771,6 +774,40 @@ The *xolox#misc#path#tempdir()* function
771774

772775
Create a temporary directory and return the pathname of the directory.
773776

777+
-------------------------------------------------------------------------------
778+
*misc-manipulation-of-unix-file-permissions*
779+
Manipulation of UNIX file permissions ~
780+
781+
Vim's |writefile()| function cannot set file permissions for newly created
782+
files and although Vim script has a function to get file permissions (see
783+
|getfperm()|) there is no equivalent for changing a file's permissions.
784+
785+
This omission breaks the otherwise very useful idiom of updating a file by
786+
writing its new contents to a temporary file and then renaming the temporary
787+
file into place (which is as close as you're going to get to atomically
788+
updating a file's contents on UNIX) because the file's permissions will not be
789+
preserved!
790+
791+
**Here's a practical example:** My vim-easytags [6] plug-in writes tags file
792+
updates to a temporary file and renames the temporary file into place. When I
793+
use 'sudo -s' on Ubuntu Linux it preserves my environment variables so my
794+
'~/.vimrc' and the vim-easytags [6] plug-in are still loaded. Now when a tags
795+
file is written the file becomes owned by root (my effective user id in the
796+
'sudo' session). Once I leave the 'sudo' session I can no longer update my tags
797+
file because it's now owned by root … ಠ_ಠ
798+
799+
-------------------------------------------------------------------------------
800+
The *xolox#misc#perm#get()* function
801+
802+
Get the permissions of the pathname given as the first argument. Returns a
803+
string which you can later pass to |xolox#misc#perm#set()|.
804+
805+
-------------------------------------------------------------------------------
806+
The *xolox#misc#perm#set()* function
807+
808+
Set the permissions (the second argument) of the pathname given as the first
809+
argument. Expects a permissions string created by |xolox#misc#perm#get()|.
810+
774811
-------------------------------------------------------------------------------
775812
*misc-persist-recall-vim-values-from-to-files*
776813
Persist/recall Vim values from/to files ~
@@ -1084,7 +1121,7 @@ Online [15].
10841121
*misc-license*
10851122
License ~
10861123

1087-
This software is licensed under the MIT license [16]. Š 2014 Peter Odding
1124+
This software is licensed under the MIT license [16]. © 2014 Peter Odding
10881125
10891126

10901127
===============================================================================

0 commit comments

Comments
 (0)