1 /* Recursively descend the filesystem and visit each file. */
20 void scandir(const string& path);
30 if ((stat_buf.st_mode & S_IFMT) != S_IFREG) {
31 printf("file is no longer a regular file!\n");
36 ssize_t res = read(fd, buf, sizeof(buf));
40 printf("Error while reading: %m\n");
42 } else if (res == 0) {
49 printf(" bytes=%Ld\n", size);
52 void scanfile(const string& path)
60 lstat(path.c_str(), &stat_buf);
62 printf("%s:\n", path.c_str());
63 printf(" ino=%Ld, perm=%04o, uid=%d, gid=%d, nlink=%d, blksize=%d, size=%Ld\n",
64 (int64_t)stat_buf.st_ino, stat_buf.st_mode & 07777,
65 stat_buf.st_uid, stat_buf.st_gid, stat_buf.st_nlink,
66 (int)stat_buf.st_blksize, (int64_t)stat_buf.st_size);
68 switch (stat_buf.st_mode & S_IFMT) {
73 printf(" special file\n");
78 /* Use the reported file size to allocate a buffer large enough to read
79 * the symlink. Allocate slightly more space, so that we ask for more
80 * bytes than we expect and so check for truncation. */
81 buf = new char[stat_buf.st_size + 2];
82 len = readlink(path.c_str(), buf, stat_buf.st_size + 1);
84 printf("error reading symlink: %m\n");
85 } else if (len <= stat_buf.st_size) {
87 printf(" contents=%s\n", buf);
88 } else if (len > stat_buf.st_size) {
89 printf("error reading symlink: name truncated\n");
94 printf(" regular file\n");
95 /* Be paranoid when opening the file. We have no guarantee that the
96 * file was not replaced between the stat() call above and the open()
97 * call below, so we might not even be opening a regular file. That
98 * the file descriptor refers to a regular file is checked in
99 * dumpfile(). But we also supply flags to open to to guard against
100 * various conditions before we can perform that verification:
101 * - O_NOFOLLOW: in the event the file was replaced by a symlink
102 * - O_NONBLOCK: prevents open() from blocking if the file was
104 * We also add in O_NOATIME, since this may reduce disk writes (for
106 fd = open(path.c_str(), O_RDONLY|O_NOATIME|O_NOFOLLOW|O_NONBLOCK);
108 /* Drop the use of the O_NONBLOCK flag; we only wanted that for file
110 flags = fcntl(fd, F_GETFL);
111 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
118 printf(" directory\n");
124 void scandir(const string& path)
126 DIR *dir = opendir(path.c_str());
129 printf("Error: %m\n");
134 vector<string> contents;
135 while ((ent = readdir(dir)) != NULL) {
136 string filename(ent->d_name);
137 if (filename == "." || filename == "..")
139 contents.push_back(filename);
142 sort(contents.begin(), contents.end());
144 for (vector<string>::iterator i = contents.begin();
145 i != contents.end(); ++i) {
146 const string& filename = *i;
147 scanfile(path + "/" + filename);
153 int main(int argc, char *argv[])