Tôi đang cố viết một chương trình C nhỏ mô phỏng lệnh unix ls -l
. Để làm như vậy, tôi đang sử dụng tòa nhà chọc trời stat(2)
và đã gặp phải một trục trặc nhỏ bằng văn bản cho phép. Tôi có một biến số mode_t
giữ quyền truy cập tệp từ st_mode
và sẽ không khó để phân tích giá trị đó thành biểu diễn chuỗi, nhưng tôi đã tự hỏi liệu có cách nào tốt hơn để thực hiện điều đó không.In tệp quyền như 'ls -l' bằng cách sử dụng chỉ số (2) trong C
Trả lời
ví dụ từ 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;
}
kết quả:
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
Những điều cơ bản là đủ đơn giản; các bit khéo léo là các bit SUID và SGID và bit dính, điều chỉnh các bit 'x'. Cân nhắc chia quyền thành 3 số bát phân cho người dùng, nhóm, chủ sở hữu và sử dụng các số đó để lập chỉ mục thành một mảng gồm các chuỗi gồm 3 ký tự như rwx
và ---
. Sau đó điều chỉnh các bit x
thích hợp dựa trên các bit chế độ khác. Loại tệp sẽ phải được xử lý riêng, nhưng bạn có thể sử dụng quyền dịch 12 bit (có thể với mặt nạ) và bảng nhập 16 để xử lý 16 giá trị có thể (không phải tất cả đều hợp lệ trên bất kỳ hệ thống nào) . Hoặc bạn có thể xử lý các loại đã biết như được hiển thị trong mã bên dưới.
+----+---+---+---+---+
|type|SSS|USR|GRP|OTH|
+----+---+---+---+---+
Bốn loại bit, ba bit S (setuid, setgid, sticky) và người dùng, nhóm và các bit khác.
Đây là mã tôi sử dụng để chuyển đổi mode_t
thành chuỗi. Nó được viết cho một chương trình không có chủ đề độc đáo, vì vậy nó sử dụng dữ liệu tĩnh; nó sẽ là tầm thường để sửa đổi nó để lấy chuỗi đầu ra làm tham số đầu vào:
/* 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);
}
Đánh giá cao độ sâu được cung cấp bởi câu trả lời của bạn! Học điều mới mỗi ngày! – cheezone
clang '' -Weverything'' khá đúng phàn nàn :) –
@ ArranCudbard-Bell: Tôi đã dọn dẹp một tập hợp các lệnh với một cái gì đó tương tự như 'clang -Weverything' và đôi lúc nó có thể hơi đau. Tôi đã không thực sự cố gắng 'clang -Weverything' trực tiếp; nó có thể ít hơn so với các tùy chọn tôi đang sử dụng (khoảng 18 '-W *' cờ; '-Wconversion' là nguyên nhân lớn nhất gây rắc rối cho mã của tôi). –
Tôi không thích cú pháp if/ else if
.
Tôi thích sử dụng câu lệnh switch
. Sau khi vật lộn một chút tôi thấy cách chúng ta có thể làm điều đó sử dụng các macro khác nhau, ví dụ:
S_ISCHR (mode)
Tương đương với:
((mode & S_IFMT) == S_IFCHR)
Điều này cho phép chúng ta xây dựng một câu lệnh switch như thế này:
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);
}
Theo ý kiến của tôi, nó thanh lịch hơn một chút so với phương pháp if/else if
.
Bạn đã bỏ mã lắp ráp để xác định mã nào hiệu quả hơn? (ví dụ: 'gcc -S -masm = intel -O2 -o filemode.asm filemode.c') –
- 1. Cách lấy "wc -l" để in chỉ số dòng mà không có tên tệp?
- 2. Cách sử dụng WHERE IN trong Rails 3 bằng cách sử dụng MySQL 2?
- 3. Kết hợp 2 tệp AAC bằng cách sử dụng Java
- 4. Chứng chỉ kỹ thuật số: Cách nhập tệp .cer vào tệp .truststore bằng cách sử dụng?
- 5. lệnh terminal là gì: ls -l hiển thị?
- 6. ls liên tục giống như đuôi (danh sách tệp)
- 7. Sử dụng enum như tham số kiểu chung trong C#
- 8. awk '{print $ 9}' cột ls-l cuối cùng bao gồm bất kỳ dấu cách nào trong tên tệp
- 9. In Excel bằng cách sử dụng Interop
- 10. Có thể in các ký tự không in bằng chỉ số% C không?
- 11. C++ xác định chỉ số mảng trong initializer, như C
- 12. Tìm tệp thi hành bằng ls và grep
- 13. Sử dụng tài nguyên như chỉ số mảng trong PHP
- 14. Tái sử dụng macro C trong một số tệp
- 15. Plugin lắp ráp Maven: Không truy xuất được thuộc tính tệp số bằng cách sử dụng: '/ bin/sh -c ls -1nlaR
- 16. Cách sử dụng OAuth 2 - OAuth 2 C# example
- 17. Chính xác C, F, L, l và M của PatternLayout (log4j) chậm như thế nào?
- 18. Đặt quyền tệp trong C#
- 19. Thực hiện lệnh ls -al trong C
- 20. Số lượng tệp trong một thư mục bằng cách sử dụng C++
- 21. Đếm số lượng tệp trong thư mục bằng cách sử dụng C
- 22. Ghi tệp vào đĩa CD bằng cách sử dụng C#
- 23. In con trỏ quay trong ứng dụng đang chạy đầu cuối bằng cách sử dụng C
- 24. Cách sử dụng ls để tìm tệp cho một tập hợp ngày cụ thể trong Unix
- 25. Đúc chuỗi phân cách bằng dấu phẩy thành số nguyên được sử dụng trong "IN" SQL
- 26. arm-no-eabi-gcc: In số phao bằng cách sử dụng printf
- 27. cho tên trong `ls` và tên tệp có dấu cách
- 28. Cách mở tệp để truy cập ghi không độc quyền bằng cách sử dụng .NET
- 29. Cách gọi hàm được viết trong tệp javascript từ C# bằng cách sử dụng IronJS
- 30. Cách sử dụng toán tử Delphi "in" trong C++ Builder
Cảm ơn câu trả lời. Điều này đã giúp một tấn. – cheezone
Lưu ý rằng vì mã sử dụng 'stat()' thay vì 'lstat()', lần duy nhất nó sẽ báo cáo 'liên kết tượng trưng' là khi liên kết tượng trưng bị hỏng. Nếu không, nó sẽ báo cáo về tệp ở cuối liên kết tượng trưng. –