PKUOS - Pintos
Pintos source browser for PKU Operating System course
pwd.c
Go to the documentation of this file.
1/** pwd.c
2
3 Prints the absolute name of the present working directory. */
4
5#include <syscall.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <string.h>
9
10static bool getcwd (char *cwd, size_t cwd_size);
11
12int
13main (void)
14{
15 char cwd[128];
16 if (getcwd (cwd, sizeof cwd))
17 {
18 printf ("%s\n", cwd);
19 return EXIT_SUCCESS;
20 }
21 else
22 {
23 printf ("error\n");
24 return EXIT_FAILURE;
25 }
26}
27
28/** Stores the inode number for FILE_NAME in *INUM.
29 Returns true if successful, false if the file could not be
30 opened. */
31static bool
32get_inumber (const char *file_name, int *inum)
33{
34 int fd = open (file_name);
35 if (fd >= 0)
36 {
37 *inum = inumber (fd);
38 close (fd);
39 return true;
40 }
41 else
42 return false;
43}
44
45/** Prepends PREFIX to the characters stored in the final *DST_LEN
46 bytes of the DST_SIZE-byte buffer that starts at DST.
47 Returns true if successful, false if adding that many
48 characters, plus a null terminator, would overflow the buffer.
49 (No null terminator is actually added or depended upon, but
50 its space is accounted for.) */
51static bool
52prepend (const char *prefix,
53 char *dst, size_t *dst_len, size_t dst_size)
54{
55 size_t prefix_len = strlen (prefix);
56 if (prefix_len + *dst_len + 1 <= dst_size)
57 {
58 *dst_len += prefix_len;
59 memcpy ((dst + dst_size) - *dst_len, prefix, prefix_len);
60 return true;
61 }
62 else
63 return false;
64}
65
66/** Stores the current working directory, as a null-terminated
67 string, in the CWD_SIZE bytes in CWD.
68 Returns true if successful, false on error. Errors include
69 system errors, directory trees deeper than MAX_LEVEL levels,
70 and insufficient space in CWD. */
71static bool
72getcwd (char *cwd, size_t cwd_size)
73{
74 size_t cwd_len = 0;
75
76#define MAX_LEVEL 20
77 char name[MAX_LEVEL * 3 + 1 + READDIR_MAX_LEN + 1];
78 char *namep;
79
80 int child_inum;
81
82 /* Make sure there's enough space for at least "/". */
83 if (cwd_size < 2)
84 return false;
85
86 /* Get inumber for current directory. */
87 if (!get_inumber (".", &child_inum))
88 return false;
89
90 namep = name;
91 for (;;)
92 {
93 int parent_inum, parent_fd;
94
95 /* Compose "../../../..", etc., in NAME. */
96 if ((namep - name) > MAX_LEVEL * 3)
97 return false;
98 *namep++ = '.';
99 *namep++ = '.';
100 *namep = '\0';
101
102 /* Open directory. */
103 parent_fd = open (name);
104 if (parent_fd < 0)
105 return false;
106 *namep++ = '/';
107
108 /* If parent and child have the same inumber,
109 then we've arrived at the root. */
110 parent_inum = inumber (parent_fd);
111 if (parent_inum == child_inum)
112 break;
113
114 /* Find name of file in parent directory with the child's
115 inumber. */
116 for (;;)
117 {
118 int test_inum;
119 if (!readdir (parent_fd, namep) || !get_inumber (name, &test_inum))
120 {
121 close (parent_fd);
122 return false;
123 }
124 if (test_inum == child_inum)
125 break;
126 }
127 close (parent_fd);
128
129 /* Prepend "/name" to CWD. */
130 if (!prepend (namep - 1, cwd, &cwd_len, cwd_size))
131 return false;
132
133 /* Move up. */
134 child_inum = parent_inum;
135 }
136
137 /* Finalize CWD. */
138 if (cwd_len > 0)
139 {
140 /* Move the string to the beginning of CWD,
141 and null-terminate it. */
142 memmove (cwd, (cwd + cwd_size) - cwd_len, cwd_len);
143 cwd[cwd_len] = '\0';
144 }
145 else
146 {
147 /* Special case for the root. */
148 strlcpy (cwd, "/", cwd_size);
149 }
150
151 return true;
152}
char * name[]
Definition: insult.c:47
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
bool readdir(int fd, char name[READDIR_MAX_LEN+1])
Definition: syscall.c:169
void close(int fd)
Definition: syscall.c:139
int open(const char *file)
Definition: syscall.c:103
int inumber(int fd)
lib/user/syscall.h
Definition: syscall.c:181
#define EXIT_SUCCESS
Typical return values from main() and arguments to exit().
Definition: syscall.h:19
#define EXIT_FAILURE
Unsuccessful execution.
Definition: syscall.h:20
#define READDIR_MAX_LEN
Maximum characters in a filename written by readdir().
Definition: syscall.h:16
#define MAX_LEVEL
int main(void)
Definition: pwd.c:13
static bool getcwd(char *cwd, size_t cwd_size)
pwd.c
Definition: pwd.c:72
static bool prepend(const char *prefix, char *dst, size_t *dst_len, size_t dst_size)
Prepends PREFIX to the characters stored in the final *DST_LEN bytes of the DST_SIZE-byte buffer that...
Definition: pwd.c:52
static bool get_inumber(const char *file_name, int *inum)
Stores the inode number for FILE_NAME in *INUM.
Definition: pwd.c:32
size_t strlen(const char *string)
Returns the length of STRING.
Definition: string.c:293
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
void * memmove(void *dst_, const void *src_, size_t size)
Copies SIZE bytes from SRC to DST, which are allowed to overlap.
Definition: string.c:24
void * memcpy(void *dst_, const void *src_, size_t size)
Copies SIZE bytes from SRC to DST, which must not overlap.
Definition: string.c:7
static const char file_name[]
tests/filesys/base/syn-read.h
Definition: syn-read.h:5