Próbuję napisać mały program w języku C, który emuluje polecenie unix ls -l
. Aby to zrobić, korzystam z syscall stat(2)
i napotkałem małą czkawkę, pisząc uprawnienia. Mam zmienną mode_t
, która przechowuje uprawnienia do plików od st_mode
i nie byłoby trudno przetworzyć tę wartość na reprezentację ciągów s, ale zastanawiałem się, czy jest lepszy sposób na zrobienie tego niż to.Drukowanie uprawnień do plików, takich jak "ls -l" przy użyciu stat (2) w C
Odpowiedz
przykład z google
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char **argv)
{
if(argc != 2)
return 1;
struct stat fileStat;
if(stat(argv[1],&fileStat) < 0)
return 1;
printf("Information for %s\n",argv[1]);
printf("---------------------------\n");
printf("File Size: \t\t%d bytes\n",fileStat.st_size);
printf("Number of Links: \t%d\n",fileStat.st_nlink);
printf("File inode: \t\t%d\n",fileStat.st_ino);
printf("File Permissions: \t");
printf((S_ISDIR(fileStat.st_mode)) ? "d" : "-");
printf((fileStat.st_mode & S_IRUSR) ? "r" : "-");
printf((fileStat.st_mode & S_IWUSR) ? "w" : "-");
printf((fileStat.st_mode & S_IXUSR) ? "x" : "-");
printf((fileStat.st_mode & S_IRGRP) ? "r" : "-");
printf((fileStat.st_mode & S_IWGRP) ? "w" : "-");
printf((fileStat.st_mode & S_IXGRP) ? "x" : "-");
printf((fileStat.st_mode & S_IROTH) ? "r" : "-");
printf((fileStat.st_mode & S_IWOTH) ? "w" : "-");
printf((fileStat.st_mode & S_IXOTH) ? "x" : "-");
printf("\n\n");
printf("The file %s a symbolic link\n", (S_ISLNK(fileStat.st_mode)) ? "is" : "is not");
return 0;
}
wynik:
Information for 2.c --------------------------- File Size: 1223 bytes Number of Links: 1 File inode: 39977236 File Permissions: -rw-r--r-- The file is not a symbolic link
Podstawy są dość proste; trudnymi bitami są bity SUID i SGID oraz lepki bit, który modyfikuje bity "x". Rozważ podzielenie uprawnień na 3 cyfry ósemkowe dla użytkownika, grupy, właściciela i przy użyciu tych, które będą indeksowane w tablicę 3-znakowych łańcuchów, takich jak rwx
i ---
. Następnie dostosuj odpowiednie bity x
w oparciu o inne bity trybu. Typ pliku będzie musiał zostać potraktowany osobno, ale możesz użyć 12-bitowego przesunięcia w prawo (prawdopodobnie z maskowaniem) i 16 tabeli wpisów, aby poradzić sobie z 16 możliwymi wartościami (nie wszystkie z nich są ważne w danym systemie) . Lub możesz radzić sobie ze znanymi typami, jak pokazano w poniższym kodzie.
+----+---+---+---+---+
|type|SSS|USR|GRP|OTH|
+----+---+---+---+---+
4 typów bity, trzy bity S (z setuidem, setgid lepkie), a użytkownik, grupa i inne bity.
Jest to kod, którego używam do przekształcania mode_t
w ciąg znaków. Został napisany dla ładnie pozbawionego nici programu, więc używa statycznych danych; byłoby trywialne zmodyfikować go do podjęcia ciąg wyjściowy jako parametr wejściowy:
/* Convert a mode field into "ls -l" type perms field. */
static char *lsperms(int mode)
{
static const char *rwx[] = {"---", "--x", "-w-", "-wx",
"r--", "r-x", "rw-", "rwx"};
static char bits[11];
bits[0] = filetypeletter(mode);
strcpy(&bits[1], rwx[(mode >> 6)& 7]);
strcpy(&bits[4], rwx[(mode >> 3)& 7]);
strcpy(&bits[7], rwx[(mode & 7)]);
if (mode & S_ISUID)
bits[3] = (mode & S_IXUSR) ? 's' : 'S';
if (mode & S_ISGID)
bits[6] = (mode & S_IXGRP) ? 's' : 'l';
if (mode & S_ISVTX)
bits[9] = (mode & S_IXOTH) ? 't' : 'T';
bits[10] = '\0';
return(bits);
}
static int filetypeletter(int mode)
{
char c;
if (S_ISREG(mode))
c = '-';
else if (S_ISDIR(mode))
c = 'd';
else if (S_ISBLK(mode))
c = 'b';
else if (S_ISCHR(mode))
c = 'c';
#ifdef S_ISFIFO
else if (S_ISFIFO(mode))
c = 'p';
#endif /* S_ISFIFO */
#ifdef S_ISLNK
else if (S_ISLNK(mode))
c = 'l';
#endif /* S_ISLNK */
#ifdef S_ISSOCK
else if (S_ISSOCK(mode))
c = 's';
#endif /* S_ISSOCK */
#ifdef S_ISDOOR
/* Solaris 2.6, etc. */
else if (S_ISDOOR(mode))
c = 'D';
#endif /* S_ISDOOR */
else
{
/* Unknown type -- possibly a regular file? */
c = '?';
}
return(c);
}
Doceń głębię dostarczoną przez odpowiedź! Naucz się czegoś nowego każdego dnia! – cheezone
clang '' -Weverything'' dość słusznie narzeka :) –
@ ArranCudbard-Bell: Sprzątałem korpus poleceń z czymś analogicznym do "clang -Weverything" i czasami może być trochę bolesne. Właściwie nie próbowałem bezpośrednio "clang -Weverything"; może być mniej uciążliwy niż opcje, których używam (około 18 '-W *' flag; '-Wconversion' jest największą przyczyną problemów z moim kodem). –
Nie lubię składni if/ else if
.
Wolę używać oświadczenia switch
. Po zmaga się trochę znalazłem sposób możemy to zrobić za pomocą różnych makr, na przykład:
S_ISCHR (mode)
jest równoznaczne z:
((mode & S_IFMT) == S_IFCHR)
Pozwala nam to na zbudowanie switch tak:
char f_type(mode_t mode)
{
char c;
switch (mode & S_IFMT)
{
case S_IFBLK:
c = 'b';
break;
case S_IFCHR:
c = 'c';
break;
case S_IFDIR:
c = 'd';
break;
case S_IFIFO:
c = 'p';
break;
case S_IFLNK:
c = 'l';
break;
case S_IFREG:
c = '-';
break;
case S_IFSOCK:
c = 's';
break;
default:
c = '?';
break;
}
return (c);
}
Co, moim zdaniem, jest nieco bardziej eleganckie niż podejście if/else if
.
Czy porzuciłeś kod zespołu, aby określić, który jest bardziej wydajny? (np. 'gcc -S -masm = intel -O2 -o filemode.asm filemode.c') –
- 1. Drukowanie przy użyciu ReportViewer - SSRS
- 2. sortowanie właścicieli ls-l w systemie Unix
- 3. zmiana uprawnień plików w pythonie
- 4. Odmowa uprawnień pomimo odpowiednich uprawnień przy użyciu PHP
- 5. Drukowanie przy użyciu szablonu
- 6. Jak przekonwertować wyjście stat do łańcucha uprawnień uniksów
- 7. Jak zażądać uprawnień administratora przy użyciu NSIS?
- 8. Skopiuj plik do komputera zdalnego przy użyciu zdalnych uprawnień administratora
- 9. Sprawdzanie uprawnień przy użyciu Global.asax
- 10. przy użyciu stat, aby wykryć, czy plik istnieje (wolno?)
- 11. Drukowanie widoku w iOS przy użyciu Swift
- 12. Zamykanie otwartych plików przy użyciu C#
- 13. Przekazywanie ścieżki db do \ l lub .Q.l przy użyciu zmiennej
- 14. Nie można ustawić uprawnień do plików w S3 przy użyciu boto i django
- 15. C# WebRequest przy użyciu plików cookie
- 16. Utrzymanie uprawnień do plików w aktualizacjach SVN?
- 17. Parsowanie i drukowanie $ PATH przy użyciu Uniksa
- 18. Jak uzyskać tylko nazwy plików w katalogu przy użyciu C#?
- 19. Unix rury do ls
- 20. Binutils stat nielegalna opcja -c
- 21. Kopiowanie uprawnień do plików, ale nie plików
- 22. ogonopodobne ciągłe ls (lista plików)
- 23. C++ setprecision (2) drukowanie jednej wartości dziesiętnej?
- 24. Modyfikowanie uprawnień do plików subversion
- 25. Drukowanie zawartości div przy użyciu Jquery
- 26. Drukowanie nazw plików
- 27. Przesyłanie plików do serwera plików przy użyciu klasy klienta WWW
- 28. Automatyczne drukowanie strony html przy użyciu javascript
- 29. Jak zaimplementować wirtualny system plików Pythona przy użyciu półki
- 30. Drukowanie aktualnego czasu w oknie wyjściowym przy użyciu TracePoint
Dzięki za odpowiedź. To pomogło tonę. – cheezone
Należy zauważyć, że ponieważ kod używa 'stat()' zamiast 'lstat()', jedyny moment, w którym zgłasza "dowiązanie symboliczne", jest po zerwaniu dowiązania symbolicznego. W przeciwnym razie będzie raportował na pliku na końcu dowiązania symbolicznego. –