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/* Generate ls-style "mode string" like "-rwsr-xr-x" or "drwxrwxrwt" */
  20
  21#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \
  22 || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \
  23 || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \
  24 || ( S_IFIFO != 0010000 )
  25# warning mode type bitflag value assumption(s) violated! falling back to larger version
  26
  27# if (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX) == 07777
  28#  undef mode_t
  29#  define mode_t unsigned short
  30# endif
  31
  32static const mode_t mode_flags[] ALIGN4 = {
  33        S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID,
  34        S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID,
  35        S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX
  36};
  37
  38/* The previous version used "0pcCd?bB-?l?s???".  However, the '0', 'C',
  39 * and 'B' types don't appear to be available on linux.  So I removed them. */
  40static const char type_chars[16] ALIGN1 = "?pc?d?b?-?l?s???";
  41/***************************************** 0123456789abcdef */
  42static const char mode_chars[7] ALIGN1 = "rwxSTst";
  43
  44char* FAST_FUNC bb_mode_string(char buf[11], mode_t mode)
  45{
  46        char *p = buf;
  47
  48        int i, j, k;
  49
  50        *p = type_chars[ (mode >> 12) & 0xf ];
  51        i = 0;
  52        do {
  53                j = k = 0;
  54                do {
  55                        *++p = '-';
  56                        if (mode & mode_flags[i+j]) {
  57                                *p = mode_chars[j];
  58                                k = j;
  59                        }
  60                } while (++j < 3);
  61                if (mode & mode_flags[i+j]) {
  62                        *p = mode_chars[3 + (k & 2) + ((i&8) >> 3)];
  63                }
  64                i += 4;
  65        } while (i < 12);
  66
  67        buf[10] = '\0';
  68
  69        return buf;
  70}
  71
  72#else
  73
  74/* The previous version used "0pcCd?bB-?l?s???".  However, the '0', 'C',
  75 * and 'B' types don't appear to be available on linux.  So I removed them. */
  76static const char type_chars[16] ALIGN1 = "?pc?d?b?-?l?s???";
  77/***************************************** 0123456789abcdef */
  78static const char mode_chars[7] ALIGN1 = "rwxSTst";
  79
  80char* FAST_FUNC bb_mode_string(char buf[11], mode_t mode)
  81{
  82        char *p = buf;
  83
  84        int i, j, k, m;
  85
  86        *p = type_chars[ (mode >> 12) & 0xf ];
  87        i = 0;
  88        m = 0400;
  89        do {
  90                j = k = 0;
  91                do {
  92                        *++p = '-';
  93                        if (mode & m) {
  94                                *p = mode_chars[j];
  95                                k = j;
  96                        }
  97                        m >>= 1;
  98                } while (++j < 3);
  99                ++i;
 100                if (mode & (010000 >> i)) {
 101                        *p = mode_chars[3 + (k & 2) + (i == 3)];
 102                }
 103        } while (i < 3);
 104
 105        buf[10] = '\0';
 106
 107        return buf;
 108}
 109
 110#endif
 111