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