(ftypelet): Add support for Cray's migrated dmf files.
[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 Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17 \f
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #if !S_IRUSR
26 # if S_IREAD
27 #  define S_IRUSR S_IREAD
28 # else
29 #  define S_IRUSR 00400
30 # endif
31 #endif
32
33 #if !S_IWUSR
34 # if S_IWRITE
35 #  define S_IWUSR S_IWRITE
36 # else
37 #  define S_IWUSR 00200
38 # endif
39 #endif
40
41 #if !S_IXUSR
42 # if S_IEXEC
43 #  define S_IXUSR S_IEXEC
44 # else
45 #  define S_IXUSR 00100
46 # endif
47 #endif
48
49 #ifdef STAT_MACROS_BROKEN
50 #undef S_ISBLK
51 #undef S_ISCHR
52 #undef S_ISDIR
53 #undef S_ISFIFO
54 #undef S_ISLNK
55 #undef S_ISMPB
56 #undef S_ISMPC
57 #undef S_ISNWK
58 #undef S_ISREG
59 #undef S_ISSOCK
60 #endif /* STAT_MACROS_BROKEN.  */
61
62 #if !defined(S_ISBLK) && defined(S_IFBLK)
63 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
64 #endif
65 #if !defined(S_ISCHR) && defined(S_IFCHR)
66 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
67 #endif
68 #if !defined(S_ISDIR) && defined(S_IFDIR)
69 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
70 #endif
71 #if !defined(S_ISREG) && defined(S_IFREG)
72 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
73 #endif
74 #if !defined(S_ISFIFO) && defined(S_IFIFO)
75 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
76 #endif
77 #if !defined(S_ISLNK) && defined(S_IFLNK)
78 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
79 #endif
80 #if !defined(S_ISSOCK) && defined(S_IFSOCK)
81 #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
82 #endif
83 #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
84 #define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
85 #define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
86 #endif
87 #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
88 #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
89 #endif
90
91 void mode_string ();
92 static char ftypelet ();
93 static void rwx ();
94 static void setst ();
95
96 /* filemodestring - fill in string STR with an ls-style ASCII
97    representation of the st_mode field of file stats block STATP.
98    10 characters are stored in STR; no terminating null is added.
99    The characters stored in STR are:
100
101    0    File type.  'd' for directory, 'c' for character
102         special, 'b' for block special, 'm' for multiplex,
103         'l' for symbolic link, 's' for socket, 'p' for fifo,
104         '-' for regular, '?' for any other file type
105
106    1    'r' if the owner may read, '-' otherwise.
107
108    2    'w' if the owner may write, '-' otherwise.
109
110    3    'x' if the owner may execute, 's' if the file is
111         set-user-id, '-' otherwise.
112         'S' if the file is set-user-id, but the execute
113         bit isn't set.
114
115    4    'r' if group members may read, '-' otherwise.
116
117    5    'w' if group members may write, '-' otherwise.
118
119    6    'x' if group members may execute, 's' if the file is
120         set-group-id, '-' otherwise.
121         'S' if it is set-group-id but not executable.
122
123    7    'r' if any user may read, '-' otherwise.
124
125    8    'w' if any user may write, '-' otherwise.
126
127    9    'x' if any user may execute, 't' if the file is "sticky"
128         (will be retained in swap space after execution), '-'
129         otherwise.
130         'T' if the file is sticky but not executable.  */
131
132 void
133 filemodestring (statp, str)
134      struct stat *statp;
135      char *str;
136 {
137   mode_string (statp->st_mode, str);
138 }
139
140 /* Like filemodestring, but only the relevant part of the `struct stat'
141    is given as an argument.  */
142
143 void
144 mode_string (mode, str)
145      unsigned short mode;
146      char *str;
147 {
148   str[0] = ftypelet ((long) mode);
149   rwx ((mode & 0700) << 0, &str[1]);
150   rwx ((mode & 0070) << 3, &str[4]);
151   rwx ((mode & 0007) << 6, &str[7]);
152   setst (mode, str);
153 }
154
155 /* Return a character indicating the type of file described by
156    file mode BITS:
157    'd' for directories
158    'b' for block special files
159    'c' for character special files
160    'm' for multiplexor files
161    'l' for symbolic links
162    's' for sockets
163    'p' for fifos
164    '-' for regular files
165    '?' for any other file type.  */
166
167 static char
168 ftypelet (bits)
169      long bits;
170 {
171 #ifdef S_ISBLK
172   if (S_ISBLK (bits))
173     return 'b';
174 #endif
175   if (S_ISCHR (bits))
176     return 'c';
177   if (S_ISDIR (bits))
178     return 'd';
179   if (S_ISREG (bits))
180     return '-';
181 #ifdef S_ISFIFO
182   if (S_ISFIFO (bits))
183     return 'p';
184 #endif
185 #ifdef S_ISLNK
186   if (S_ISLNK (bits))
187     return 'l';
188 #endif
189 #ifdef S_ISSOCK
190   if (S_ISSOCK (bits))
191     return 's';
192 #endif
193 #ifdef S_ISMPC
194   if (S_ISMPC (bits))
195     return 'm';
196 #endif
197 #ifdef S_ISNWK
198   if (S_ISNWK (bits))
199     return 'n';
200 #endif
201
202 #ifdef S_ISOFD
203   /* Cray migrated dmf file.  */
204   if (S_ISOFD (bits))
205     return 'M';
206 #endif
207 #ifdef S_ISOFL
208   /* Cray migrated dmf file.  */
209   if (S_ISOFL (bits))
210     return 'M';
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_IRUSR) ? 'r' : '-';
224   chars[1] = (bits & S_IWUSR) ? 'w' : '-';
225   chars[2] = (bits & S_IXUSR) ? '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 }