Author:Wang Shanshan, a lecturer at Huaqing vision embedded College.
Many practical examples show that the best way to learn is to apply relevant knowledge points to specific examples. In this way, we not only know the principle, but also how to apply it. When learning file IO, we can try to write the LS command. Therefore, before writing the LS command, we must specify what the LS command can do before we can know how to write the LS command.
In fact, there are many ls Parameter options, most of which can be used in combination. We must make it clear that implementing our own LS command is not in place in one step. We must first learn how to implement its basic functions. Here, I use the simplest
Ls-l (specific file)
In this example, we will analyze how to write Linux commands.
How can we output the printed information of the terminal in a specific format? To accomplish this specific function, we need to complete the following two steps:
1. How to obtain file information
2. How to output file information according to format rules
The following is a further analysis:
Step 1: obtain file information.
In the C library, we provide a set of functions to obtain the attributes of files (common files, directories, pipelines, sockets, characters, blocks.
Their function prototype
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <unistd. h>
Int Stat (const char * path, struct stat * BUF);/* provides the file name to obtain the corresponding attributes of the file. */
Int fstat (INT filedes, struct stat * BUF);/* Get the attributes of the file through the file descriptor. */
Int lstat (const char * path, struct stat * BUF);/* connect to the file description to get the file attributes. */
The difference between stat and lstat is that for a linked file, stat displays the actual file attribute pointed to by the linked file, that is, the information of the referenced file of the symbolic link is returned, the lstat displays information about the symbolic link.
Parameter: Path:
File Path Name. Filedes: The description of a file.
Buf: a pointer to the following struct to describe the attributes of the file.
Struct stat
{
Dev_t st_dev;/* identifier of the device where the file is located */
Ino_t st_ino;/* file node number */
Mode_t st_mode;/* file protection mode */
Nlink_t st_nlink;/* Number of hard connections */
Uid_t st_uid;/* file user ID */
Gid_t st_gid;/* file user group ID */
Dev_t st_rdev;/* indicates the device ID of the special device file in the file */
Off_t st_size;/* Total size, in bytes */
Blksize_t st_blksize;/* block size of the file system */
Blkcnt_t st_blocks;/* number of blocks allocated to the file. The unit is 512 bytes */
Time_t st_atime;/* last access time */
Time_t st_mtime;/* last modification time */
Time_t st_ctime;/* last state change time */
};
Function implementation:
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <time. h>
# Include <fcntl. h>
# Include <stdio. h>
# Include <PWD. h>
# Include <GRP. h>
# Include <unistd. h>
Int main (INT argc, char * argv [])
{If (argc <2)
{
Printf ("Commend error! /N ");
Return-1;
}
Int I;
Struct stat Buf;
Char out [500];
Char * P;
If (lstat (argv [1], & BUF) =-1)
{
// Printf ("No such file/N ");
Return-1;
}
}
At this time, we have obtained the Buf struct. From this struct, we can easily write the following information, which is easier to implement:
// Number of connections
Printf ("% d", Buf. st_nlink );
// User ID
Struct passwd * user;
User = getpwuid (BUF. st_uid );
Printf ("% s", user-> pw_name );
// Group ID
Struct Group * group;
Group = getgrgid (BUF. st_gid );
Printf ("% s", group-> gr_name );
// Size
Printf ("% d", Buf. st_size );
// Time
Struct TM * t;
T = localtime (& Buf. st_ctime );
Printf ("% d-% d: % d", T-> maid + 1900,
T-> tm_mon + 1,
T-> tm_mday,
T-> tm_hour,
T-> tm_sec );
Printf ("% s", argv [1]);
So far, the file type and the read and write permissions of users, groups, and other users have not been parsed. In fact, the information we need is included in the st_mode of the Buf, you only need to parse the returned st_mode to obtain the required information.
Let's take a look at the file type. How can we determine the file type? You can use a mask to decode the file type. <Sys/STAT. h> has the following definitions:
# Define s_ifmt 0170000
# Define s_ifreg 0100000
# Define s_ifdir 0040000
# Define s_ifblk 0060000
....
To determine whether the file type is a common file, write the following code:
If (info. st_mode & 0170000) = 0100000)
Printf ("this is a regular file ");
Of course, we can also implement the macro defined in <sys/STAT. h>.
# Define s_isfifo (m) & (0170000) = (0010000 ))
# Define s_isreg (m) & (0170000) = 0100000 ))
....
Therefore, you can also write the following code:
If (s_isdir (info. st_mode ))
Printf ("this is a regular file ");
Now we will continue to add programs that have not been written:
If (s_isreg (BUF. st_mode) P = "-";
Else if (s_isdir (BUF. st_mode) P = "R ";
Else if (s_ischr (BUF. st_mode) P = "C ";
Else if (s_isblk (BUF. st_mode) P = "B ";
Else if (s_isfifo (BUF. st_mode) P = "F ";
Else if (s_islnk (BUF. st_mode) P = "L ";
Else if (s_issock (BUF. st_mode) P = "S ";
The remaining file describes how to implement the permissions of different users. Similarly, the above method is used for implementation.
Int N;
For (n = 8; n> = 0; n --)
{
If (BUF. st_mode & (1 <n ))
Switch (N % 3)
{
Case 2: printf ("R"); break;
Case 1: printf ("W"); break;
Case 0: printf ("X"); break;
}
Else
Printf ("-");
}
In this way, the four paragraphs are written together to implement the LS-L-specific file function.