12159047fSniklas /* filemode.c -- make a string describing file modes
2*007c2a45Smiod    Copyright 1985, 1990, 1991, 1994, 1995, 1997, 2003
3b55d4692Sfgsch    Free Software Foundation, Inc.
42159047fSniklas 
52159047fSniklas    This program is free software; you can redistribute it and/or modify
62159047fSniklas    it under the terms of the GNU General Public License as published by
72159047fSniklas    the Free Software Foundation; either version 2, or (at your option)
82159047fSniklas    any later version.
92159047fSniklas 
102159047fSniklas    This program is distributed in the hope that it will be useful,
112159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
122159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
132159047fSniklas    GNU General Public License for more details.
142159047fSniklas 
152159047fSniklas    You should have received a copy of the GNU General Public License
162159047fSniklas    along with this program; if not, write to the Free Software
17fddef416Sniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18fddef416Sniklas    02111-1307, USA.  */
192159047fSniklas 
202159047fSniklas #include "bfd.h"
21fddef416Sniklas #include "bucomm.h"
222159047fSniklas 
23*007c2a45Smiod static char ftypelet (unsigned long);
24*007c2a45Smiod static void setst (unsigned long, char *);
252159047fSniklas 
262159047fSniklas /* filemodestring - fill in string STR with an ls-style ASCII
272159047fSniklas    representation of the st_mode field of file stats block STATP.
282159047fSniklas    10 characters are stored in STR; no terminating null is added.
292159047fSniklas    The characters stored in STR are:
302159047fSniklas 
312159047fSniklas    0	File type.  'd' for directory, 'c' for character
322159047fSniklas 	special, 'b' for block special, 'm' for multiplex,
332159047fSniklas 	'l' for symbolic link, 's' for socket, 'p' for fifo,
342159047fSniklas 	'-' for any other file type
352159047fSniklas 
362159047fSniklas    1	'r' if the owner may read, '-' otherwise.
372159047fSniklas 
382159047fSniklas    2	'w' if the owner may write, '-' otherwise.
392159047fSniklas 
402159047fSniklas    3	'x' if the owner may execute, 's' if the file is
412159047fSniklas 	set-user-id, '-' otherwise.
422159047fSniklas 	'S' if the file is set-user-id, but the execute
432159047fSniklas 	bit isn't set.
442159047fSniklas 
452159047fSniklas    4	'r' if group members may read, '-' otherwise.
462159047fSniklas 
472159047fSniklas    5	'w' if group members may write, '-' otherwise.
482159047fSniklas 
492159047fSniklas    6	'x' if group members may execute, 's' if the file is
502159047fSniklas 	set-group-id, '-' otherwise.
512159047fSniklas 	'S' if it is set-group-id but not executable.
522159047fSniklas 
532159047fSniklas    7	'r' if any user may read, '-' otherwise.
542159047fSniklas 
552159047fSniklas    8	'w' if any user may write, '-' otherwise.
562159047fSniklas 
572159047fSniklas    9	'x' if any user may execute, 't' if the file is "sticky"
582159047fSniklas 	(will be retained in swap space after execution), '-'
592159047fSniklas 	otherwise.
602159047fSniklas 	'T' if the file is sticky but not executable.  */
612159047fSniklas 
622159047fSniklas #if 0
632159047fSniklas 
642159047fSniklas /* This is not used; only mode_string is used.  */
652159047fSniklas 
662159047fSniklas void
67*007c2a45Smiod filemodestring (struct stat *statp, char *str)
682159047fSniklas {
692159047fSniklas   mode_string ((unsigned long) statp->st_mode, str);
702159047fSniklas }
712159047fSniklas 
722159047fSniklas #endif
732159047fSniklas 
742159047fSniklas /* Get definitions for the file permission bits.  */
752159047fSniklas 
762159047fSniklas #ifndef S_IRWXU
772159047fSniklas #define S_IRWXU 0700
782159047fSniklas #endif
792159047fSniklas #ifndef S_IRUSR
802159047fSniklas #define S_IRUSR 0400
812159047fSniklas #endif
822159047fSniklas #ifndef S_IWUSR
832159047fSniklas #define S_IWUSR 0200
842159047fSniklas #endif
852159047fSniklas #ifndef S_IXUSR
862159047fSniklas #define S_IXUSR 0100
872159047fSniklas #endif
882159047fSniklas 
892159047fSniklas #ifndef S_IRWXG
902159047fSniklas #define S_IRWXG 0070
912159047fSniklas #endif
922159047fSniklas #ifndef S_IRGRP
932159047fSniklas #define S_IRGRP 0040
942159047fSniklas #endif
952159047fSniklas #ifndef S_IWGRP
962159047fSniklas #define S_IWGRP 0020
972159047fSniklas #endif
982159047fSniklas #ifndef S_IXGRP
992159047fSniklas #define S_IXGRP 0010
1002159047fSniklas #endif
1012159047fSniklas 
1022159047fSniklas #ifndef S_IRWXO
1032159047fSniklas #define S_IRWXO 0007
1042159047fSniklas #endif
1052159047fSniklas #ifndef S_IROTH
1062159047fSniklas #define S_IROTH 0004
1072159047fSniklas #endif
1082159047fSniklas #ifndef S_IWOTH
1092159047fSniklas #define S_IWOTH 0002
1102159047fSniklas #endif
1112159047fSniklas #ifndef S_IXOTH
1122159047fSniklas #define S_IXOTH 0001
1132159047fSniklas #endif
1142159047fSniklas 
1152159047fSniklas /* Like filemodestring, but only the relevant part of the `struct stat'
1162159047fSniklas    is given as an argument.  */
1172159047fSniklas 
1182159047fSniklas void
mode_string(unsigned long mode,char * str)119*007c2a45Smiod mode_string (unsigned long mode, char *str)
1202159047fSniklas {
1212159047fSniklas   str[0] = ftypelet ((unsigned long) mode);
1222159047fSniklas   str[1] = (mode & S_IRUSR) != 0 ? 'r' : '-';
1232159047fSniklas   str[2] = (mode & S_IWUSR) != 0 ? 'w' : '-';
1242159047fSniklas   str[3] = (mode & S_IXUSR) != 0 ? 'x' : '-';
1252159047fSniklas   str[4] = (mode & S_IRGRP) != 0 ? 'r' : '-';
1262159047fSniklas   str[5] = (mode & S_IWGRP) != 0 ? 'w' : '-';
1272159047fSniklas   str[6] = (mode & S_IXGRP) != 0 ? 'x' : '-';
1282159047fSniklas   str[7] = (mode & S_IROTH) != 0 ? 'r' : '-';
1292159047fSniklas   str[8] = (mode & S_IWOTH) != 0 ? 'w' : '-';
1302159047fSniklas   str[9] = (mode & S_IXOTH) != 0 ? 'x' : '-';
1312159047fSniklas   setst ((unsigned long) mode, str);
1322159047fSniklas }
1332159047fSniklas 
1342159047fSniklas /* Return a character indicating the type of file described by
1352159047fSniklas    file mode BITS:
1362159047fSniklas    'd' for directories
1372159047fSniklas    'b' for block special files
1382159047fSniklas    'c' for character special files
139*007c2a45Smiod    'm' for multiplexer files
1402159047fSniklas    'l' for symbolic links
1412159047fSniklas    's' for sockets
1422159047fSniklas    'p' for fifos
1432159047fSniklas    '-' for any other file type.  */
1442159047fSniklas 
1452159047fSniklas #ifndef S_ISDIR
1462159047fSniklas #ifdef S_IFDIR
1472159047fSniklas #define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR)
1482159047fSniklas #else /* ! defined (S_IFDIR) */
1492159047fSniklas #define S_ISDIR(i) (((i) & 0170000) == 040000)
1502159047fSniklas #endif /* ! defined (S_IFDIR) */
1512159047fSniklas #endif /* ! defined (S_ISDIR) */
1522159047fSniklas 
1532159047fSniklas #ifndef S_ISBLK
1542159047fSniklas #ifdef S_IFBLK
1552159047fSniklas #define S_ISBLK(i) (((i) & S_IFMT) == S_IFBLK)
1562159047fSniklas #else /* ! defined (S_IFBLK) */
1572159047fSniklas #define S_ISBLK(i) 0
1582159047fSniklas #endif /* ! defined (S_IFBLK) */
1592159047fSniklas #endif /* ! defined (S_ISBLK) */
1602159047fSniklas 
1612159047fSniklas #ifndef S_ISCHR
1622159047fSniklas #ifdef S_IFCHR
1632159047fSniklas #define S_ISCHR(i) (((i) & S_IFMT) == S_IFCHR)
1642159047fSniklas #else /* ! defined (S_IFCHR) */
1652159047fSniklas #define S_ISCHR(i) 0
1662159047fSniklas #endif /* ! defined (S_IFCHR) */
1672159047fSniklas #endif /* ! defined (S_ISCHR) */
1682159047fSniklas 
1692159047fSniklas #ifndef S_ISFIFO
1702159047fSniklas #ifdef S_IFIFO
1712159047fSniklas #define S_ISFIFO(i) (((i) & S_IFMT) == S_IFIFO)
1722159047fSniklas #else /* ! defined (S_IFIFO) */
1732159047fSniklas #define S_ISFIFO(i) 0
1742159047fSniklas #endif /* ! defined (S_IFIFO) */
1752159047fSniklas #endif /* ! defined (S_ISFIFO) */
1762159047fSniklas 
1772159047fSniklas #ifndef S_ISSOCK
1782159047fSniklas #ifdef S_IFSOCK
1792159047fSniklas #define S_ISSOCK(i) (((i) & S_IFMT) == S_IFSOCK)
1802159047fSniklas #else /* ! defined (S_IFSOCK) */
1812159047fSniklas #define S_ISSOCK(i) 0
1822159047fSniklas #endif /* ! defined (S_IFSOCK) */
1832159047fSniklas #endif /* ! defined (S_ISSOCK) */
1842159047fSniklas 
1852159047fSniklas #ifndef S_ISLNK
1862159047fSniklas #ifdef S_IFLNK
1872159047fSniklas #define S_ISLNK(i) (((i) & S_IFMT) == S_IFLNK)
1882159047fSniklas #else /* ! defined (S_IFLNK) */
1892159047fSniklas #define S_ISLNK(i) 0
1902159047fSniklas #endif /* ! defined (S_IFLNK) */
1912159047fSniklas #endif /* ! defined (S_ISLNK) */
1922159047fSniklas 
1932159047fSniklas static char
ftypelet(unsigned long bits)194*007c2a45Smiod ftypelet (unsigned long bits)
1952159047fSniklas {
1962159047fSniklas   if (S_ISDIR (bits))
1972159047fSniklas     return 'd';
1982159047fSniklas   if (S_ISLNK (bits))
1992159047fSniklas     return 'l';
2002159047fSniklas   if (S_ISBLK (bits))
2012159047fSniklas     return 'b';
2022159047fSniklas   if (S_ISCHR (bits))
2032159047fSniklas     return 'c';
2042159047fSniklas   if (S_ISSOCK (bits))
2052159047fSniklas     return 's';
2062159047fSniklas   if (S_ISFIFO (bits))
2072159047fSniklas     return 'p';
2082159047fSniklas 
2092159047fSniklas #ifdef S_IFMT
2102159047fSniklas #ifdef S_IFMPC
2112159047fSniklas   if ((bits & S_IFMT) == S_IFMPC
2122159047fSniklas       || (bits & S_IFMT) == S_IFMPB)
2132159047fSniklas     return 'm';
2142159047fSniklas #endif
2152159047fSniklas #ifdef S_IFNWK
2162159047fSniklas   if ((bits & S_IFMT) == S_IFNWK)
2172159047fSniklas     return 'n';
2182159047fSniklas #endif
2192159047fSniklas #endif
2202159047fSniklas 
2212159047fSniklas   return '-';
2222159047fSniklas }
2232159047fSniklas 
2242159047fSniklas /* Set the 's' and 't' flags in file attributes string CHARS,
2252159047fSniklas    according to the file mode BITS.  */
2262159047fSniklas 
2272159047fSniklas static void
setst(unsigned long bits ATTRIBUTE_UNUSED,char * chars ATTRIBUTE_UNUSED)228*007c2a45Smiod setst (unsigned long bits ATTRIBUTE_UNUSED, char *chars ATTRIBUTE_UNUSED)
2292159047fSniklas {
2302159047fSniklas #ifdef S_ISUID
2312159047fSniklas   if (bits & S_ISUID)
2322159047fSniklas     {
2332159047fSniklas       if (chars[3] != 'x')
2342159047fSniklas 	/* Set-uid, but not executable by owner.  */
2352159047fSniklas 	chars[3] = 'S';
2362159047fSniklas       else
2372159047fSniklas 	chars[3] = 's';
2382159047fSniklas     }
2392159047fSniklas #endif
2402159047fSniklas #ifdef S_ISGID
2412159047fSniklas   if (bits & S_ISGID)
2422159047fSniklas     {
2432159047fSniklas       if (chars[6] != 'x')
2442159047fSniklas 	/* Set-gid, but not executable by group.  */
2452159047fSniklas 	chars[6] = 'S';
2462159047fSniklas       else
2472159047fSniklas 	chars[6] = 's';
2482159047fSniklas     }
2492159047fSniklas #endif
2502159047fSniklas #ifdef S_ISVTX
2512159047fSniklas   if (bits & S_ISVTX)
2522159047fSniklas     {
2532159047fSniklas       if (chars[9] != 'x')
2542159047fSniklas 	/* Sticky, but not executable by others.  */
2552159047fSniklas 	chars[9] = 'T';
2562159047fSniklas       else
2572159047fSniklas 	chars[9] = 't';
2582159047fSniklas     }
2592159047fSniklas #endif
2602159047fSniklas }
261