Implementation of copy
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "%s <source-file> <destination-file>.\n", argv[0]);
return kWrongArgumentCount;
}
int fdin = open(argv[1], /* flags = */ O_RDONLY);
if (fdin == -1) {
fprintf(stderr, "%s: source file could not be opened.\n", argv[1]);
return kSourceFileNonExistent;
}
int fdout = open(argv[2], /* flags = */ O_WRONLY | O_CREAT | O_EXCL, 0644);
if (fdout == -1) {
switch (errno) {
case EEXIST:
fprintf(stderr, "%s: destination file already exists.\n", argv[2]);
break;
default:
fprintf(stderr, "%s: destination file could not be created.\n", argv[2]);
break;
}
return kDestinationFileOpenFailure;
}Implementation of copy, continued
char buffer[1024];
while (true) {
ssize_t bytesRead = read(fdin, buffer, sizeof(buffer));
if (bytesRead == 0) break;
if (bytesRead == -1) {
fprintf(stderr, "%s: lost access to file while reading.\n", argv[1]);
return kReadFailure;
}
size_t bytesWritten = 0;
while (bytesWritten < bytesRead) {
ssize_t count = write(fdout, buffer + bytesWritten, bytesRead - bytesWritten);
if (count == -1) {
fprintf(stderr, "%s: lost access to file while writing.\n", argv[2]);
return kWriteFailure;
}
bytesWritten += count;
}
}
if (close(fdin) == -1) fprintf(stderr, "%s: had trouble closing file.\n", argv[1]);
if (close(fdout) == -1) fprintf(stderr, "%s: had trouble closing file.\n", argv[2]);
return 0;
}
myth4> cat alphabet.txt | tee one.txt two.txt three.txt
abcdefghijklmnopqrstuvwxyz
myth4> cat one.txt
abcdefghijklmnopqrstuvwxyz
myth4> cat two.txt
abcdefghijklmnopqrstuvwxyz
myth4> diff one.txt two.txt
myth4> diff one.txt three.txt
myth4>
myth4> more vowels.txt | tee one.txt
aeiou
myth4> more one.txt
aeiou
myth4> more two.txt
abcdefghijklmnopqrstuvwxyz
myth4>
Implementation of t
static void writeall(int fd, const char buffer[], size_t len) {
size_t numWritten = 0;
while (numWritten < len) {
numWritten += write(fd, buffer + numWritten, len - numWritten);
}
}
int main(int argc, char *argv[]) {
int fds[argc];
fds[0] = STDOUT_FILENO;
for (size_t i = 1; i < argc; i++)
fds[i] = open(argv[i], O_WRONLY | O_CREAT | O_TRUNC, 0644);
char buffer[2048];
while (true) {
ssize_t numRead = read(STDIN_FILENO, buffer, sizeof(buffer));
if (numRead == 0) break;
for (size_t i = 0; i < argc; i++)
writeall(fds[i], buffer, numRead);
}
for (size_t i = 1; i < argc; i++) close(fds[i]);
return 0;
}
dev_t st_dev ID of device containing file
ino_t st_ino file serial number
mode_t st_mode mode of file
nlink_t st_nlink number of links to the file
uid_t st_uid user ID of file
gid_t st_gid group ID of file
dev_t st_rdev device ID (if file is character or block special)
off_t st_size file size in bytes (if file is a regular file)
time_t st_atime time of last access
time_t st_mtime time of last data modification
time_t st_ctime time of last status change
blksize_t st_blksize a filesystem-specific preferred I/O block size for
this object. In some filesystem types, this may
vary from file to file
blkcnt_t st_blocks number of blocks allocated for this object
static void exitUnless(bool test, FILE *stream, int code, const char *control, ...) {
if (test) return;
va_list arglist;
va_start(arglist, control);
vfprintf(stream, control, arglist);
va_end(arglist);
exit(code);
}
int main(int argc, char *argv[]) {
exitUnless(argc == 3, stderr, kWrongArgumentCount,
"Usage: %s <directory> <pattern>\n", argv[0]);
struct stat st;
const char *directory = argv[1];
stat(directory, &st);
exitUnless(S_ISDIR(st.st_mode), stderr, kDirectoryNeeded,
"<directory> must be an actual directory, %s is not", directory);
size_t length = strlen(directory);
if (length > kMaxPath) return 0;
const char *pattern = argv[2];
char path[kMaxPath + 1];
strcpy(path, directory); // no buffer overflow because of above check
listMatches(path, length, pattern);
return 0;
}Implementation of listMatches
static void listMatches(char path[], size_t length, const char *pattern) {
DIR *dir = opendir(path);
if (dir == NULL) return; // path isn't a directory
strcpy(path + length, "/");
while (true) {
struct dirent *de = readdir(dir);
if (de == NULL) break;
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
if (length + strlen(de->d_name) + 1 > kMaxPath) continue;
strcpy(path + length + 1, de->d_name);
struct stat st;
lstat(path, &st);
if (S_ISREG(st.st_mode)) {
if (strstr(de->d_name, pattern) != NULL) {
printf("%s\n", path);
}
} else if (S_ISDIR(st.st_mode)) {
listMatches(path, length + 1 + strlen(de->d_name), pattern);
}
}
closedir(dir);
}myth7> list /usr/class/cs110/WWW
drwxr-xr-x 8 70296 root 2048 Sep 24 15:07 .
drwxr-xr-x >9 root root 2048 Sep 25 12:46 ..
drwxr-xr-x 2 70296 root 2048 Sep 24 09:23 restricted
drwx------ 2 poohbear operator 2048 Sep 24 09:23 repos
drwx------ >9 poohbear operator 2048 Sep 25 16:29 autumn-2017
-rw------- 1 poohbear operator 89 Sep 24 15:03 index.html
Implementation of list's listPermissions:
static inline void updatePermissionsBit(bool flag, char permissions[], size_t column, char ch) {
if (flag) permissions[column] = ch;
}
static const size_t kNumPermissionColumns = 10;
static const char kPermissionChars[] = {'r', 'w', 'x'};
static const size_t kNumPermissionChars = sizeof(kPermissionChars);
static const mode_t kPermissionFlags[] = {
S_IRUSR, S_IWUSR, S_IXUSR, // user flags
S_IRGRP, S_IWGRP, S_IXGRP, // group flags
S_IROTH, S_IWOTH, S_IXOTH // everyone (other) flags
};
static const size_t kNumPermissionFlags = sizeof(kPermissionFlags)/sizeof(kPermissionFlags[0]);
static void listPermissions(mode_t mode) {
char permissions[kNumPermissionColumns + 1];
memset(permissions, '-', sizeof(permissions));
permissions[kNumPermissionColumns] = '\0';
updatePermissionsBit(S_ISDIR(mode), permissions, 0, 'd');
updatePermissionsBit(S_ISLNK(mode), permissions, 0, 'l');
for (size_t i = 0; i < kNumPermissionFlags; i++) {
updatePermissionsBit(mode & kPermissionFlags[i], permissions, i + 1,
kPermissionChars[i % kNumPermissionChars]);
}
printf("%s ", permissions);
}