]> code.delx.au - gnu-emacs/blob - src/filemode.c
a1fc388638b540b6dda034fbd9448fc7a6c32fb9
[gnu-emacs] / src / filemode.c
1 /* filemode.c -- make a string describing file modes
2 Copyright (C) 1985, 1990, 1993, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 USA. */
19 \f
20 #include <config.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23
24 #if !S_IRUSR
25 # if S_IREAD
26 # define S_IRUSR S_IREAD
27 # else
28 # define S_IRUSR 00400
29 # endif
30 #endif
31
32 #if !S_IWUSR
33 # if S_IWRITE
34 # define S_IWUSR S_IWRITE
35 # else
36 # define S_IWUSR 00200
37 # endif
38 #endif
39
40 #if !S_IXUSR
41 # if S_IEXEC
42 # define S_IXUSR S_IEXEC
43 # else
44 # define S_IXUSR 00100
45 # endif
46 #endif
47
48 #ifdef STAT_MACROS_BROKEN
49 #undef S_ISBLK
50 #undef S_ISCHR
51 #undef S_ISDIR
52 #undef S_ISFIFO
53 #undef S_ISLNK
54 #undef S_ISMPB
55 #undef S_ISMPC
56 #undef S_ISNWK
57 #undef S_ISREG
58 #undef S_ISSOCK
59 #endif /* STAT_MACROS_BROKEN. */
60
61 #if !defined(S_ISBLK) && defined(S_IFBLK)
62 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
63 #endif
64 #if !defined(S_ISCHR) && defined(S_IFCHR)
65 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
66 #endif
67 #if !defined(S_ISDIR) && defined(S_IFDIR)
68 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
69 #endif
70 #if !defined(S_ISREG) && defined(S_IFREG)
71 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
72 #endif
73 #if !defined(S_ISFIFO) && defined(S_IFIFO)
74 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
75 #endif
76 #if !defined(S_ISLNK) && defined(S_IFLNK)
77 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
78 #endif
79 #if !defined(S_ISSOCK) && defined(S_IFSOCK)
80 #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
81 #endif
82 #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
83 #define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
84 #define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
85 #endif
86 #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
87 #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
88 #endif
89
90 void mode_string (short unsigned int mode, char *str);
91 static char ftypelet (long int bits);
92 static void rwx (short unsigned int bits, char *chars);
93 static void setst (short unsigned int bits, char *chars);
94
95 /* filemodestring - fill in string STR with an ls-style ASCII
96 representation of the st_mode field of file stats block STATP.
97 10 characters are stored in STR; no terminating null is added.
98 The characters stored in STR are:
99
100 0 File type. 'd' for directory, 'c' for character
101 special, 'b' for block special, 'm' for multiplex,
102 'l' for symbolic link, 's' for socket, 'p' for fifo,
103 '-' for regular, '?' for any other file type
104
105 1 'r' if the owner may read, '-' otherwise.
106
107 2 'w' if the owner may write, '-' otherwise.
108
109 3 'x' if the owner may execute, 's' if the file is
110 set-user-id, '-' otherwise.
111 'S' if the file is set-user-id, but the execute
112 bit isn't set.
113
114 4 'r' if group members may read, '-' otherwise.
115
116 5 'w' if group members may write, '-' otherwise.
117
118 6 'x' if group members may execute, 's' if the file is
119 set-group-id, '-' otherwise.
120 'S' if it is set-group-id but not executable.
121
122 7 'r' if any user may read, '-' otherwise.
123
124 8 'w' if any user may write, '-' otherwise.
125
126 9 'x' if any user may execute, 't' if the file is "sticky"
127 (will be retained in swap space after execution), '-'
128 otherwise.
129 'T' if the file is sticky but not executable. */
130
131 void
132 filemodestring (struct stat *statp, char *str)
133 {
134 mode_string (statp->st_mode, str);
135 }
136
137 /* Like filemodestring, but only the relevant part of the `struct stat'
138 is given as an argument. */
139
140 void
141 mode_string (short unsigned int mode, char *str)
142 {
143 str[0] = ftypelet ((long) mode);
144 rwx ((mode & 0700) << 0, &str[1]);
145 rwx ((mode & 0070) << 3, &str[4]);
146 rwx ((mode & 0007) << 6, &str[7]);
147 setst (mode, str);
148 }
149
150 /* Return a character indicating the type of file described by
151 file mode BITS:
152 'd' for directories
153 'b' for block special files
154 'c' for character special files
155 'm' for multiplexor files
156 'l' for symbolic links
157 's' for sockets
158 'p' for fifos
159 '-' for regular files
160 '?' for any other file type. */
161
162 static char
163 ftypelet (long int bits)
164 {
165 #ifdef S_ISBLK
166 if (S_ISBLK (bits))
167 return 'b';
168 #endif
169 if (S_ISCHR (bits))
170 return 'c';
171 if (S_ISDIR (bits))
172 return 'd';
173 if (S_ISREG (bits))
174 return '-';
175 #ifdef S_ISFIFO
176 if (S_ISFIFO (bits))
177 return 'p';
178 #endif
179 #ifdef S_ISLNK
180 if (S_ISLNK (bits))
181 return 'l';
182 #endif
183 #ifdef S_ISSOCK
184 if (S_ISSOCK (bits))
185 return 's';
186 #endif
187 #ifdef S_ISMPC
188 if (S_ISMPC (bits))
189 return 'm';
190 #endif
191 #ifdef S_ISNWK
192 if (S_ISNWK (bits))
193 return 'n';
194 #endif
195 return '?';
196 }
197
198 /* Look at read, write, and execute bits in BITS and set
199 flags in CHARS accordingly. */
200
201 static void
202 rwx (short unsigned int bits, char *chars)
203 {
204 chars[0] = (bits & S_IRUSR) ? 'r' : '-';
205 chars[1] = (bits & S_IWUSR) ? 'w' : '-';
206 chars[2] = (bits & S_IXUSR) ? 'x' : '-';
207 }
208
209 /* Set the 's' and 't' flags in file attributes string CHARS,
210 according to the file mode BITS. */
211
212 static void
213 setst (short unsigned int bits, char *chars)
214 {
215 #ifdef S_ISUID
216 if (bits & S_ISUID)
217 {
218 if (chars[3] != 'x')
219 /* Set-uid, but not executable by owner. */
220 chars[3] = 'S';
221 else
222 chars[3] = 's';
223 }
224 #endif
225 #ifdef S_ISGID
226 if (bits & S_ISGID)
227 {
228 if (chars[6] != 'x')
229 /* Set-gid, but not executable by group. */
230 chars[6] = 'S';
231 else
232 chars[6] = 's';
233 }
234 #endif
235 #ifdef S_ISVTX
236 if (bits & S_ISVTX)
237 {
238 if (chars[9] != 'x')
239 /* Sticky, but not executable by others. */
240 chars[9] = 'T';
241 else
242 chars[9] = 't';
243 }
244 #endif
245 }
246