Merge from coreutils.
[gnulib.git] / lib / filemode.c
1 /* filemode.c -- make a string describing file modes
2    Copyright (C) 1985, 1990, 1993, 1998-2000, 2004 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
18 #if HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #include "filemode.h"
26 #include "stat-macros.h"
27
28
29 /* Set the 's' and 't' flags in file attributes string CHARS,
30    according to the file mode BITS.  */
31
32 static void
33 setst (mode_t bits, char *chars)
34 {
35   if (bits & S_ISUID)
36     {
37       if (chars[3] != 'x')
38         /* Set-uid, but not executable by owner.  */
39         chars[3] = 'S';
40       else
41         chars[3] = 's';
42     }
43   if (bits & S_ISGID)
44     {
45       if (chars[6] != 'x')
46         /* Set-gid, but not executable by group.  */
47         chars[6] = 'S';
48       else
49         chars[6] = 's';
50     }
51   if (bits & S_ISVTX)
52     {
53       if (chars[9] != 'x')
54         /* Sticky, but not executable by others.  */
55         chars[9] = 'T';
56       else
57         chars[9] = 't';
58     }
59 }
60
61 /* Return a character indicating the type of file described by
62    file mode BITS:
63    'd' for directories
64    'D' for doors
65    'b' for block special files
66    'c' for character special files
67    'n' for network special files
68    'm' for multiplexor files
69    'M' for an off-line (regular) file
70    'l' for symbolic links
71    's' for sockets
72    'p' for fifos
73    'C' for contigous data files
74    '-' for regular files
75    '?' for any other file type.  */
76
77 static char
78 ftypelet (mode_t bits)
79 {
80   if (S_ISBLK (bits))
81     return 'b';
82   if (S_ISCHR (bits))
83     return 'c';
84   if (S_ISDIR (bits))
85     return 'd';
86   if (S_ISREG (bits))
87     return '-';
88   if (S_ISFIFO (bits))
89     return 'p';
90   if (S_ISLNK (bits))
91     return 'l';
92   if (S_ISSOCK (bits))
93     return 's';
94   if (S_ISMPC (bits))
95     return 'm';
96   if (S_ISNWK (bits))
97     return 'n';
98   if (S_ISDOOR (bits))
99     return 'D';
100   if (S_ISCTG (bits))
101     return 'C';
102
103   /* The following two tests are for Cray DMF (Data Migration
104      Facility), which is a HSM file system.  A migrated file has a
105      `st_dm_mode' that is different from the normal `st_mode', so any
106      tests for migrated files should use the former.  */
107
108   if (S_ISOFD (bits))
109     /* off line, with data  */
110     return 'M';
111   /* off line, with no data  */
112   if (S_ISOFL (bits))
113     return 'M';
114   return '?';
115 }
116
117 /* Like filemodestring, but only the relevant part of the `struct stat'
118    is given as an argument.  */
119
120 void
121 mode_string (mode_t mode, char *str)
122 {
123   str[0] = ftypelet (mode);
124   str[1] = mode & S_IRUSR ? 'r' : '-';
125   str[2] = mode & S_IWUSR ? 'w' : '-';
126   str[3] = mode & S_IXUSR ? 'x' : '-';
127   str[4] = mode & S_IRGRP ? 'r' : '-';
128   str[5] = mode & S_IWGRP ? 'w' : '-';
129   str[6] = mode & S_IXGRP ? 'x' : '-';
130   str[7] = mode & S_IROTH ? 'r' : '-';
131   str[8] = mode & S_IWOTH ? 'w' : '-';
132   str[9] = mode & S_IXOTH ? 'x' : '-';
133   setst (mode, str);
134 }
135
136 /* filemodestring - fill in string STR with an ls-style ASCII
137    representation of the st_mode field of file stats block STATP.
138    10 characters are stored in STR; no terminating null is added.
139    The characters stored in STR are:
140
141    0    File type.  'd' for directory, 'c' for character
142         special, 'b' for block special, 'm' for multiplex,
143         'l' for symbolic link, 's' for socket, 'p' for fifo,
144         '-' for regular, '?' for any other file type
145
146    1    'r' if the owner may read, '-' otherwise.
147
148    2    'w' if the owner may write, '-' otherwise.
149
150    3    'x' if the owner may execute, 's' if the file is
151         set-user-id, '-' otherwise.
152         'S' if the file is set-user-id, but the execute
153         bit isn't set.
154
155    4    'r' if group members may read, '-' otherwise.
156
157    5    'w' if group members may write, '-' otherwise.
158
159    6    'x' if group members may execute, 's' if the file is
160         set-group-id, '-' otherwise.
161         'S' if it is set-group-id but not executable.
162
163    7    'r' if any user may read, '-' otherwise.
164
165    8    'w' if any user may write, '-' otherwise.
166
167    9    'x' if any user may execute, 't' if the file is "sticky"
168         (will be retained in swap space after execution), '-'
169         otherwise.
170         'T' if the file is sticky but not executable.  */
171
172 void
173 filemodestring (struct stat *statp, char *str)
174 {
175   mode_string (statp->st_mode, str);
176 }