CS318 - Pintos
Pintos source browser for JHU CS318 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 
10 static bool getcwd (char *cwd, size_t cwd_size);
11 
12 int
13 main (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. */
31 static bool
32 get_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.) */
51 static bool
52 prepend (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. */
71 static bool
72 getcwd (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 }
name
char * name[]
Definition: insult.c:47
readdir
bool readdir(int fd, char name[READDIR_MAX_LEN+1])
Definition: syscall.c:169
string.h
memcpy
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
stdbool.h
MAX_LEVEL
#define MAX_LEVEL
memmove
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
EXIT_FAILURE
#define EXIT_FAILURE
Unsuccessful execution.
Definition: syscall.h:20
getcwd
static bool getcwd(char *cwd, size_t cwd_size)
pwd.c
Definition: pwd.c:72
printf
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
open
int open(const char *file)
Definition: syscall.c:103
EXIT_SUCCESS
#define EXIT_SUCCESS
Typical return values from main() and arguments to exit().
Definition: syscall.h:19
main
int main(void)
Definition: pwd.c:13
prepend
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
inumber
int inumber(int fd)
lib/user/syscall.h
Definition: syscall.c:181
file_name
static const char file_name[]
tests/filesys/base/syn-read.h
Definition: syn-read.h:5
READDIR_MAX_LEN
#define READDIR_MAX_LEN
Maximum characters in a filename written by readdir().
Definition: syscall.h:16
strlen
size_t strlen(const char *string)
Returns the length of STRING.
Definition: string.c:293
close
void close(int fd)
Definition: syscall.c:139
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
get_inumber
static bool get_inumber(const char *file_name, int *inum)
Stores the inode number for FILE_NAME in *INUM.
Definition: pwd.c:32