1/* vi: set sw=4 ts=4: */ 2/* 3 * mode_string implementation for busybox 4 * 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 */ 9 10/* Aug 13, 2003 11 * Fix a bug reported by junkio@cox.net involving the mode_chars index. 12 */ 13 14 15#include <assert.h> 16#include <sys/stat.h> 17 18#include "libbb.h" 19 20#if ( S_ISUID != 04000 ) || ( S_ISGID != 02000 ) || ( S_ISVTX != 01000 ) \ 21 || ( S_IRUSR != 00400 ) || ( S_IWUSR != 00200 ) || ( S_IXUSR != 00100 ) \ 22 || ( S_IRGRP != 00040 ) || ( S_IWGRP != 00020 ) || ( S_IXGRP != 00010 ) \ 23 || ( S_IROTH != 00004 ) || ( S_IWOTH != 00002 ) || ( S_IXOTH != 00001 ) 24#error permission bitflag value assumption(s) violated! 25#endif 26 27#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \ 28 || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \ 29 || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \ 30 || ( S_IFIFO != 0010000 ) 31#warning mode type bitflag value assumption(s) violated! falling back to larger version 32 33#if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777 34#undef mode_t 35#define mode_t unsigned short 36#endif 37 38static const mode_t mode_flags[] = { 39 S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, 40 S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, 41 S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX 42}; 43 44/* The static const char arrays below are duplicated for the two cases 45 * because moving them ahead of the mode_flags declaration cause a text 46 * size increase with the gcc version I'm using. */ 47 48/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C', 49 * and 'B' types don't appear to be available on linux. So I removed them. */ 50static const char type_chars[16] ALIGN1 = "?pc?d?b?-?l?s???"; 51/***************************************** 0123456789abcdef */ 52static const char mode_chars[7] ALIGN1 = "rwxSTst"; 53 54const char* FAST_FUNC bb_mode_string(mode_t mode) 55{ 56 static char buf[12]; 57 char *p = buf; 58 59 int i, j, k; 60 61 *p = type_chars[ (mode >> 12) & 0xf ]; 62 i = 0; 63 do { 64 j = k = 0; 65 do { 66 *++p = '-'; 67 if (mode & mode_flags[i+j]) { 68 *p = mode_chars[j]; 69 k = j; 70 } 71 } while (++j < 3); 72 if (mode & mode_flags[i+j]) { 73 *p = mode_chars[3 + (k & 2) + ((i&8) >> 3)]; 74 } 75 i += 4; 76 } while (i < 12); 77 78 /* Note: We don't bother with nul termination because bss initialization 79 * should have taken care of that for us. If the user scribbled in buf 80 * memory, they deserve whatever happens. But we'll at least assert. */ 81 assert(buf[10] == 0); 82 83 return buf; 84} 85 86#else 87 88/* The previous version used "0pcCd?bB-?l?s???". However, the '0', 'C', 89 * and 'B' types don't appear to be available on linux. So I removed them. */ 90static const char type_chars[16] = "?pc?d?b?-?l?s???"; 91/********************************** 0123456789abcdef */ 92static const char mode_chars[7] = "rwxSTst"; 93 94const char* FAST_FUNC bb_mode_string(mode_t mode) 95{ 96 static char buf[12]; 97 char *p = buf; 98 99 int i, j, k, m; 100 101 *p = type_chars[ (mode >> 12) & 0xf ]; 102 i = 0; 103 m = 0400; 104 do { 105 j = k = 0; 106 do { 107 *++p = '-'; 108 if (mode & m) { 109 *p = mode_chars[j]; 110 k = j; 111 } 112 m >>= 1; 113 } while (++j < 3); 114 ++i; 115 if (mode & (010000 >> i)) { 116 *p = mode_chars[3 + (k & 2) + (i == 3)]; 117 } 118 } while (i < 3); 119 120 /* Note: We don't bother with nul termination because bss initialization 121 * should have taken care of that for us. If the user scribbled in buf 122 * memory, they deserve whatever happens. But we'll at least assert. */ 123 assert(buf[10] == 0); 124 125 return buf; 126} 127 128#endif 129