FreeNOS
ListFiles.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <dirent.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <limits.h>
26 #include <libgen.h>
27 #include <TerminalCodes.h>
28 #include "ListFiles.h"
29 
30 ListFiles::ListFiles(int argc, char **argv)
31  : POSIXApplication(argc, argv)
32 {
33  parser().setDescription("List files on the filesystem");
34  parser().registerPositional("FILE", "Target file to list", 0);
35  parser().registerFlag('l', "long", "List files in long output format");
36  parser().registerFlag('a', "all", "List all files on the filesystem");
37  parser().registerFlag('n', "no-color", "Set to disable terminal color output");
38 }
39 
41 {
42 }
43 
45 {
46  const Vector<Argument *> & positionals = arguments().getPositionals();
47  Result result = Success, ret = Success;
48 
49  // List files provided on the command-line, if any
50  if (positionals.count() > 0)
51  {
52  for (Size i = 0; i < positionals.count(); i++)
53  {
54  result = printFiles(positionals[i]->getValue());
55 
56  // Update the return result
57  if (result != Success)
58  {
59  ret = result;
60  }
61  }
62  }
63  // Otherwise, list the current directory
64  else
65  {
66  char path[PATH_MAX];
67  getcwd(path, sizeof(path));
68 
69  ret = printFiles(path);
70  }
71 
72  // Done
73  return ret;
74 }
75 
77 {
78  struct dirent *dent;
79  struct stat st;
80  char tmp[PATH_MAX];
81  String out;
82  DIR *d;
83  Result r = Success;
84 
85  // Retrieve file status
86  if (stat(*path, &st) != 0)
87  {
88  ERROR("failed to stat '" << *path << "': " << strerror(errno));
89  return IOError;
90  }
91 
92  // Is the given file a directory?
93  if (S_ISDIR(st.st_mode))
94  {
95  // Attempt to open the directory
96  if (!(d = opendir(*path)))
97  {
98  ERROR("failed to open '" << *path << "': " << strerror(errno));
99  return IOError;
100  }
101 
102  // Read directory
103  while ((dent = readdir(d)))
104  {
105  // Construct full path
106  snprintf(tmp, sizeof(tmp),
107  "%s/%s", *path, dent->d_name);
108 
109  if ((r = printSingleFile(tmp, out)) != Success)
110  break;
111  }
112  // Close it
113  closedir(d);
114  }
115  // The given file is not a directory
116  else
117  {
118  r = printSingleFile(path, out);
119  }
120 
121  // Final newline
122  if (!arguments().get("long"))
123  out << "\r\n";
124 
125  // Write to standard output
126  write(1, *out, out.length());
127 
128  // Success
129  return r;
130 }
131 
133 {
134  const bool color = arguments().get("no-color") == ZERO;
135  struct stat st;
136 
137  // Retrieve file status
138  if (stat(*path, &st) != 0)
139  {
140  ERROR("failed to stat '" << *path << "': " << strerror(errno));
141  return IOError;
142  }
143 
144  // Apply long output
145  if (arguments().get("long"))
146  {
147  if (color)
148  {
149  out << WHITE;
150  }
151  out << (st.st_mode & S_IRUSR ? "r" : "-");
152  out << (st.st_mode & S_IWUSR ? "w" : "-");
153  out << (st.st_mode & S_IXUSR ? "x" : "-");
154  out << (st.st_mode & S_IRGRP ? "r" : "-");
155  out << (st.st_mode & S_IWGRP ? "w" : "-");
156  out << (st.st_mode & S_IXGRP ? "x" : "-");
157  out << (st.st_mode & S_IROTH ? "r" : "-");
158  out << (st.st_mode & S_IWOTH ? "w" : "-");
159  out << (st.st_mode & S_IXOTH ? "x" : "-");
160 
161  out << " uid:" << st.st_uid << " ";
162  out.pad(23);
163 
164  out << " gid:" << st.st_gid << " ";
165  out.pad(33);
166 
167  out << " " << st.st_size << " ";
168  out.pad(43);
169  }
170 
171  // Apply coloring
172  if (color)
173  {
174  if (S_ISDIR(st.st_mode))
175  out << BLUE;
176 
177  else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
178  out << YELLOW;
179 
180  // Is the file executable?
181  else if (st.st_mode & 0100)
182  out << GREEN;
183  else
184  out << WHITE;
185  }
186 
187  out << basename((char *) *path) << " ";
188 
189  if (color)
190  {
191  out << WHITE;
192  }
193 
194  // Long output needs a newline
195  if (arguments().get("long"))
196  out << "\r\n";
197 
198  // Done
199  return Success;
200 }
S_ISBLK
#define S_ISBLK(m)
Test for a block special file.
Definition: stat.h:149
ArgumentContainer::get
const char * get(const char *name) const
Get argument by name.
Definition: ArgumentContainer.cpp:49
stat::st_size
off_t st_size
For regular files, the file size in bytes.
Definition: stat.h:226
S_ISDIR
#define S_ISDIR(m)
Test for a directory.
Definition: stat.h:155
S_IRUSR
#define S_IRUSR
Read permission, owner.
Definition: stat.h:100
stat
The <sys/stat.h> header shall define the stat structure.
Definition: stat.h:176
GREEN
@ GREEN
Definition: VGA.h:68
String::pad
String & pad(const Size length)
Pad line with trailing whitespace.
Definition: String.cpp:332
write
ssize_t write(int fildes, const void *buf, size_t nbyte)
Write on a file.
Definition: write.cpp:22
errno
C int errno
The lvalue errno is used by many functions to return error values.
stat::st_uid
uid_t st_uid
User ID of file.
Definition: stat.h:209
String::length
Size length() const
Same as count().
Definition: String.cpp:105
string.h
ListFiles.h
TerminalCodes.h
getcwd
char * getcwd(char *buf, size_t size)
Get the pathname of the current working directory.
Definition: getcwd.cpp:24
String
Abstraction of strings.
Definition: String.h:41
closedir
int closedir(DIR *dirp)
Close a directory stream.
Definition: closedir.cpp:22
readdir
struct dirent * readdir(DIR *dirp)
Read a directory.
Definition: readdir.cpp:21
S_IRGRP
#define S_IRGRP
Read permission, group.
Definition: stat.h:112
libgen.h
S_IWUSR
#define S_IWUSR
Write permission, owner.
Definition: stat.h:103
POSIXApplication
POSIX-compatible application.
Definition: POSIXApplication.h:35
Application::Success
@ Success
Definition: Application.h:55
PATH_MAX
#define PATH_MAX
Maximum file path length.
Definition: limits.h:37
Application::arguments
const ArgumentContainer & arguments() const
Get program arguments.
Definition: Application.cpp:112
opendir
DIR * opendir(const char *dirname)
Open directory associated with file descriptor.
Definition: opendir.cpp:27
ArgumentParser::setDescription
void setDescription(const String &desc)
Set program description.
Definition: ArgumentParser.cpp:95
limits.h
dirent.h
S_IWOTH
#define S_IWOTH
Write permission, others.
Definition: stat.h:127
Application::IOError
@ IOError
Definition: Application.h:57
S_IXGRP
#define S_IXGRP
Execute/search permission, group.
Definition: stat.h:118
S_ISCHR
#define S_ISCHR(m)
Test for a character special file.
Definition: stat.h:152
basename
char * basename(char *path)
Return the last component of a pathname.
Definition: basename.cpp:21
ListFiles::exec
virtual Result exec()
Execute the application.
Definition: ListFiles.cpp:44
dirent
Represents a directory entry.
Definition: dirent.h:64
WHITE
@ WHITE
Definition: VGA.h:81
S_IROTH
#define S_IROTH
Read permission, others.
Definition: stat.h:124
BLUE
@ BLUE
Definition: VGA.h:67
Vector::count
virtual Size count() const
Returns the number of items inside the Vector.
Definition: Vector.h:204
stdio.h
strerror
char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition: strerror.cpp:20
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
stat::st_mode
mode_t st_mode
Mode of file.
Definition: stat.h:203
Application::Result
Result
Result codes.
Definition: Application.h:53
ListFiles::printSingleFile
Result printSingleFile(const String &path, String &out) const
List single file on the filesystem.
Definition: ListFiles.cpp:132
ArgumentParser::registerFlag
Result registerFlag(char arg, const char *name, const char *description)
Register a flag Argument.
Definition: ArgumentParser.cpp:100
S_IXUSR
#define S_IXUSR
Execute/search permission, owner.
Definition: stat.h:106
stat
int stat(const char *path, struct stat *buf)
Get file status.
Definition: stat.cpp:25
ListFiles::~ListFiles
virtual ~ListFiles()
Destructor.
Definition: ListFiles.cpp:40
ArgumentParser::registerPositional
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
Definition: ArgumentParser.cpp:119
stat.h
DIR
A type representing a directory stream.
Definition: dirent.h:94
unistd.h
Application::parser
ArgumentParser & parser()
Get program arguments parser.
Definition: Application.cpp:102
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
S_IWGRP
#define S_IWGRP
Write permission, group.
Definition: stat.h:115
stat::st_gid
gid_t st_gid
Group ID of file.
Definition: stat.h:212
dirent::d_name
char d_name[DIRLEN]
Name of entry.
Definition: dirent.h:67
ListFiles::ListFiles
ListFiles(int argc, char **argv)
Constructor.
Definition: ListFiles.cpp:30
stdlib.h
YELLOW
#define YELLOW
Definition: TerminalCodes.h:41
S_IXOTH
#define S_IXOTH
Execute/search permission, others.
Definition: stat.h:130
ListFiles::printFiles
Result printFiles(const String &path) const
List files on the filesystem.
Definition: ListFiles.cpp:76
Vector< Argument * >
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
snprintf
int snprintf(char *buffer, unsigned int size, const char *fmt,...)
Write a formatted string into a buffer.
Definition: snprintf.cpp:22
errno.h
ArgumentContainer::getPositionals
const Vector< Argument * > & getPositionals() const
Get positional arguments.
Definition: ArgumentContainer.cpp:39