Apue Note - Files And Directories
Notes of APUE
stat, fstat, fstatat, and lstat Functions
The biggest user of the stat functions is probably the ls -l
command, to
learn all the information about a file.
File Types
- Regular file
- The most common type of file, which contains data of some form. There is no distinction to the UNIX kernel whether this data is text or binary.
- Directory file
- A file that contains the names of other files and pointers to information on these files. Any process that has read permission for a directory file can read the contents of the directory, but only the kernel can write directly to a directory file. Processes must use the functions to make changes to a directory.
- Block special file
- A type of file providing buffered I/O access in fixed-size units to devices such as disk drives.
- Character special file
- A type of file providing unbuffered I/O access in variable-sized units to devices.
- FIFO
- A type of file used for communication between processes. It’s sometimes called a named pipe.
- Socket
- A type of file used for network communication between processes.
- Symbolic link
- A type of file that points to another file.
Prints the type of file for each command-line argument:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr;
for (i = 1; i < argc; ++i) {
printf("%s: ", argv[i]);
if (lstat(argv[i], &buf) < 0) {
printf("lstat error\n");
continue;
}
if (S_ISREG(buf.st_mode))
ptr = "regular";
else if (S_ISDIR(buf.st_mode))
ptr = "directory";
else if (S_ISCHR(buf.st_mode))
ptr = "character special";
else if (S_ISBLK(buf.st_mode))
ptr = "block special";
else if (S_ISFIFO(buf.st_mode))
ptr = "fifo";
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else if (S_ISSOCK(buf.st_mode))
ptr = "socket";
else
ptr = "** unknown mode **";
printf("%s\n", ptr);
}
}
Test:
$ ./a.out /etc/passwd /etc /dev/log /dev/tty
/etc/passwd: regular
/etc: symbolic link
/dev/log: lstat error
/dev/tty: character special
access and faccessat Functions
The use of the access function
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (argc != 2)
printf("usage: a.out <pathname>\n");
if (access(argv[1], R_OK) < 0)
printf("access error for %s\n", argv[1]);
else
printf("read access OK\n");
if (open(argv[1], O_RDONLY) < 0)
printf("open error for %s\n", argv[1]);
else
printf("open for reading OK\n");
}
Test
$ ./a.out a.out
read access OK
open for reading OK
$ ./a.out /etc/shadow
access error for /etc/shadow
open error for /etc/shadow
umask Function
The umask function sets the file mode creation mask for the process and returns the previous value. Any bits that are on in the file mode creation mask are turned off in the file’s mode. The umask() function is always successful.
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int main()
{
umask(0);
if (creat("foo", RWRWRW) < 0)
printf("creat error for foo\n");
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (creat("bar", RWRWRW) < 0)
printf("creat error for bar\n");
}
Test
$ ls -l foo bar
-rw------- 1 mitnk staff 0 May 10 19:41 bar
-rw-rw-rw- 1 mitnk staff 0 May 10 19:41 foo
chmod, fchmod, and fchmodat Functions
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
struct stat statbuf;
/* turn on set-group-ID and turn off group-execute */
if (stat("foo", &statbuf) < 0)
printf("stat error for foo\n");
if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
printf("chmod error for foo\n");
/* set absolute mode to "rw-r--r--" */
if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)
printf("chmod error for bar\n");
}
Test
$ ./a.out
$ ls -l foo bar
-rw-r--r-- 1 mitnk staff 0 May 10 19:41 bar
-rw-rwSrw- 1 mitnk staff 0 May 10 19:41 foo
chown, fchown, fchownat, and lchown Functions
The chown functions allow us to change a file’s user ID and group ID.
File Size
The st_size
member of the stat structure contains the size of the file in
bytes. This field is meaningful only for regular files, directories, and
symbolic links.
For a symbolic link, the file size is the number of bytes in the filename.
Holes in a File
$ ls -l core
-rw-r--r-- 1 sar 8483248 Nov 18 12:18 core
$ du -s core
272 core
$ wc -c core
8483248 core
File Truncation
Sometimes we would like to truncate a file by chopping off data at the end
of the file. truncate
and ftruncate
are for this.
link, linkat, unlink, unlinkat, and remove Functions
Opens a file and then unlinks it.
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
if (open("tempfile", O_RDWR) < 0)
printf("open error\n");
if (unlink("tempfile") < 0)
printf("unlink error\n");
printf("file unlinked\n");
sleep(15);
printf("done\n");
}
The process creates a file using either open
or creat
and then
immediately calls unlink
. The file is not deleted, however, because it is
still open. Only when the process either closes the file or terminates,
which causes the kernel to close all its open files, is the file deleted.
futimens, utimensat, and utimes Functions
truncates files to zero length using the O_TRUNC
option of the open
function, but does not change their access time or modification time.
To do this, the program first obtains the times with the stat function,
truncates the file, and then resets the times with the futimens function.
To be continued ..