ls -lの表示を変えてみる
Head First C 読書会#01 - 名古屋C言語勉強会 | Doorkeeperの時間で、ls -lの表示を変えてみたので、その記録を。 パーミッション表示を755みたいな感じになるようにしてみました。
まずは、ls.cより、ls -lのオプションを処理している所を探す。
1644 while (true) 1645 { 1646 int oi = -1; 1647 int c = getopt_long (argc, argv, 1648 "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1", 1649 long_options, &oi); 1650 if (c == -1) 1651 break; 1652 1653 switch (c) 1654 { 1706 case 'l': 1707 format = long_format; 1708 break;
よりlオプションを指定すると、long_formatとなるようです。 色々あさった結果、
3613 case long_format: 3614 for (i = 0; i < cwd_n_used; i++) 3615 { 3616 set_normal_color (); 3617 print_long_format (sorted_file[i]); 3618 DIRED_PUTCHAR ('\n'); 3619 }
で呼ばれている print_long_format で1ラインを表示していました。
3782 /* Print information about F in long format. */ 3783 static void 3784 print_long_format (const struct fileinfo *f) 3785 { ・・・ 3803 if (f->stat_ok) 3804 filemodestring (&f->stat, modebuf); 3805 else 3806 { 3807 modebuf[0] = filetype_letter[f->filetype]; 3808 memset (modebuf + 1, '?', 10); 3809 modebuf[11] = '\0'; 3810 }
printfを間に挟みつつ探った結果、filemodestring内でmodebufにパーミッション部分が格納されている事が分かりました。 filemodestringは、filemode.cというcoreutilsとはまた別のファイルで定義されています。
165 void 166 filemodestring (struct stat const *statp, char *str) 167 { 168 strmode (statp->st_mode, str); 169 170 if (S_TYPEISSEM (statp)) 171 str[0] = 'F'; 172 else if (IS_MIGRATED_FILE (statp)) 173 str[0] = 'M'; 174 else if (S_TYPEISMQ (statp)) 175 str[0] = 'Q'; 176 else if (S_TYPEISSHM (statp)) 177 str[0] = 'S'; 178 else if (S_TYPEISTMO (statp)) 179 str[0] = 'T'; 180 }
これを下記に書き換えたら、一応狙い通りいけました。
121 void 122 mystrmode (mode_t mode, char *str) 123 { 124 char c; 125 126 c = '0'; 127 c += mode & S_IRUSR ? 4 : 0; 128 c += mode & S_IWUSR ? 2 : 0; 129 c += (mode & S_ISUID 130 ? (mode & S_IXUSR ? 0 : 0) 131 : (mode & S_IXUSR ? 1 : 0)); 132 str[0] = c; 133 134 c = '0'; 135 c += mode & S_IRGRP ? 4 : 0; 136 c += mode & S_IWGRP ? 2 : 0; 137 c += (mode & S_ISGID 138 ? (mode & S_IXGRP ? 0 : 0) 139 : (mode & S_IXGRP ? 1 : 0)); 140 str[1] = c; 141 142 c = '0'; 143 c += mode & S_IROTH ? 4 : 0; 144 c += mode & S_IWOTH ? 2 : 0; 145 c += (mode & S_ISVTX 146 ? (mode & S_IXOTH ? 0 : 0) 147 : (mode & S_IXOTH ? 1 : 0)); 148 str[2] = c; 149 150 str[3] = (mode & S_ISUID 151 ? (mode & S_IXUSR ? 's' : 'S') 152 : (mode & S_IXUSR ? ' ' : ' ')); 153 str[4] = (mode & S_ISGID 154 ? (mode & S_IXGRP ? 's' : 'S') 155 : (mode & S_IXGRP ? ' ' : ' ')); 156 str[5] = (mode & S_ISVTX 157 ? (mode & S_IXOTH ? 't' : 'T') 158 : (mode & S_IXOTH ? ' ' : ' ')); 159 160 str[6] = ' '; 161 str[7] = '\0'; 162 } ・・・ 209 void 210 filemodestring (struct stat const *statp, char *str) 211 { 212 strmode (statp->st_mode, str); 213 mystrmode (statp->st_mode, str); 214
最初、strmodeが#ifdefで無効になっているのに気づかず変更して、変更したのに動かないってハマったのが悔しい。