00001
00002
00003
00004
00005
00006 #include <syscall.h>
00007 #include <stdbool.h>
00008 #include <stdio.h>
00009 #include <string.h>
00010
00011 static bool getcwd (char *cwd, size_t cwd_size);
00012
00013 int
00014 main (void)
00015 {
00016 char cwd[128];
00017 if (getcwd (cwd, sizeof cwd))
00018 {
00019 printf ("%s\n", cwd);
00020 return EXIT_SUCCESS;
00021 }
00022 else
00023 {
00024 printf ("error\n");
00025 return EXIT_FAILURE;
00026 }
00027 }
00028
00029
00030
00031
00032 static bool
00033 get_inumber (const char *file_name, int *inum)
00034 {
00035 int fd = open (file_name);
00036 if (fd >= 0)
00037 {
00038 *inum = inumber (fd);
00039 close (fd);
00040 return true;
00041 }
00042 else
00043 return false;
00044 }
00045
00046
00047
00048
00049
00050
00051
00052 static bool
00053 prepend (const char *prefix,
00054 char *dst, size_t *dst_len, size_t dst_size)
00055 {
00056 size_t prefix_len = strlen (prefix);
00057 if (prefix_len + *dst_len + 1 <= dst_size)
00058 {
00059 *dst_len += prefix_len;
00060 memcpy ((dst + dst_size) - *dst_len, prefix, prefix_len);
00061 return true;
00062 }
00063 else
00064 return false;
00065 }
00066
00067
00068
00069
00070
00071
00072 static bool
00073 getcwd (char *cwd, size_t cwd_size)
00074 {
00075 size_t cwd_len = 0;
00076
00077 #define MAX_LEVEL 20
00078 char name[MAX_LEVEL * 3 + 1 + READDIR_MAX_LEN + 1];
00079 char *namep;
00080
00081 int child_inum;
00082
00083
00084 if (cwd_size < 2)
00085 return false;
00086
00087
00088 if (!get_inumber (".", &child_inum))
00089 return false;
00090
00091 namep = name;
00092 for (;;)
00093 {
00094 int parent_inum, parent_fd;
00095
00096
00097 if ((namep - name) > MAX_LEVEL * 3)
00098 return false;
00099 *namep++ = '.';
00100 *namep++ = '.';
00101 *namep = '\0';
00102
00103
00104 parent_fd = open (name);
00105 if (parent_fd < 0)
00106 return false;
00107 *namep++ = '/';
00108
00109
00110
00111 parent_inum = inumber (parent_fd);
00112 if (parent_inum == child_inum)
00113 break;
00114
00115
00116
00117 for (;;)
00118 {
00119 int test_inum;
00120 if (!readdir (parent_fd, namep) || !get_inumber (name, &test_inum))
00121 {
00122 close (parent_fd);
00123 return false;
00124 }
00125 if (test_inum == child_inum)
00126 break;
00127 }
00128 close (parent_fd);
00129
00130
00131 if (!prepend (namep - 1, cwd, &cwd_len, cwd_size))
00132 return false;
00133
00134
00135 child_inum = parent_inum;
00136 }
00137
00138
00139 if (cwd_len > 0)
00140 {
00141
00142
00143 memmove (cwd, (cwd + cwd_size) - cwd_len, cwd_len);
00144 cwd[cwd_len] = '\0';
00145 }
00146 else
00147 {
00148
00149 strlcpy (cwd, "/", cwd_size);
00150 }
00151
00152 return true;
00153 }