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