17
17
#include <emscripten.h>
18
18
#endif
19
19
20
- void setup () {
21
- int rtn = mkdir ("working" , 0777 );
22
- assert (rtn == 0 );
23
- #if defined(__EMSCRIPTEN__ ) && defined(NODEFS )
24
- EM_ASM (FS .mount (NODEFS , { root : '.' }, 'working' ));
25
- #endif
26
- rtn = chdir ("working" );
20
+ void makedir (const char * dir ) {
21
+ int rtn = mkdir (dir , 0777 );
27
22
assert (rtn == 0 );
28
- symlink ("../test/../there!" , "link" );
29
- int fd = open ("file" , O_RDWR | O_CREAT , 0777 );
23
+ }
24
+
25
+ void makefile (const char * file , const char * content ) {
26
+ int fd = open (file , O_RDWR | O_CREAT , 0777 );
30
27
assert (fd >= 0 );
31
- rtn = write (fd , "test" , 5 );
32
- assert (rtn == 5 );
28
+ int rtn = write (fd , content , strlen ( content ) );
29
+ assert (rtn == strlen ( content ) );
33
30
close (fd );
34
- rtn = mkdir ("folder" , 0777 );
31
+ }
32
+
33
+ void makelink (const char * link , const char * path ) {
34
+ int rtn = symlink (link , path );
35
35
assert (rtn == 0 );
36
36
}
37
37
38
- int main () {
39
- setup ();
38
+ void changedir (const char * dir ) {
39
+ int rtn = chdir (dir );
40
+ assert (rtn == 0 );
41
+ }
40
42
41
- char * files [] = {"link" , "file" , "folder" };
42
- char buffer [256 ] = {0 };
43
- int ret ;
43
+ void setup () {
44
+ makedir ("working" );
45
+ #if defined(__EMSCRIPTEN__ ) && defined(NODEFS )
46
+ EM_ASM (FS .mount (NODEFS , { root : '.' }, 'working' ));
47
+ #endif
48
+ changedir ("working" );
49
+ makelink ("../test/../there!" , "link" );
50
+ makefile ("file" , "test" );
51
+ makedir ("directory" );
52
+ makedir ("directory/subdirectory" );
53
+ makefile ("directory/subdirectory/file" , "Subdirectory" );
54
+
55
+ makedir ("relative" );
56
+ makedir ("relative/subrelative" );
57
+ makefile ("relative/file" , "Relative" );
58
+ makefile ("relative/subrelative/file" , "Subrelative" );
59
+ makelink ("../relative/file" , "directory/relative" );
60
+ makelink ("../../relative/subrelative/file" , "directory/subdirectory/subrelative" );
61
+ makelink ("directory/subdirectory/file" , "subdirectoryrelative" );
62
+
63
+ makedir ("absolute" );
64
+ makedir ("absolute/subabsolute" );
65
+ makefile ("absolute/file" , "Absolute" );
66
+ makefile ("absolute/subabsolute/file" , "Subabsolute" );
67
+ makelink ("/working/absolute/file" , "/working/directory/absolute" );
68
+ makelink ("/working/absolute/subabsolute/file" , "/working/directory/subdirectory/subabsolute" );
69
+ makelink ("/working/directory/subdirectory/file" , "/working/subdirectoryabsolute" );
70
+ }
71
+
72
+ void test_reading_existing_symlinks () {
73
+ char * files [] = {"link" , "file" , "directory" };
44
74
45
75
for (int i = 0 ; i < sizeof files / sizeof files [0 ]; i ++ ) {
46
- printf ( "readlink(%s)\n" , files [ i ]) ;
47
- ret = readlink (files [i ], buffer , 256 );
48
- printf ("errno: %s \n" , strerror ( errno ) );
49
- if ( ret < 0 ) {
50
- printf ( "not a link\n\n" );
76
+ char buffer [ 256 ] = { 0 } ;
77
+ int rtn = readlink (files [i ], buffer , 256 );
78
+ printf ("readlink: '%s' \n" , files [ i ] );
79
+ printf ( "errno: %s\n\n" , strerror ( errno ));
80
+ if ( rtn < 0 ) {
51
81
continue ;
52
82
}
83
+
53
84
// WASMFS behaves the same as Linux (and as best as I can tell, the spec),
54
85
// seeing the symlink as a string. The old JS FS instead normalizes it and
55
86
// returns something modified.
@@ -59,56 +90,125 @@ int main() {
59
90
#else
60
91
assert (strcmp (buffer , "/there!" ) == 0 );
61
92
#endif
62
- assert (strlen (buffer ) == ret );
93
+ assert (strlen (buffer ) == rtn );
63
94
errno = 0 ;
64
- printf ("\n" );
65
95
}
96
+ }
66
97
67
- printf ( "symlink/overwrite\n" );
68
- ret = symlink ("new-nonexistent-path" , "link" );
69
- assert (ret == -1 );
98
+ void test_overwriting_symlink () {
99
+ int rtn = symlink ("new-nonexistent-path" , "link" );
100
+ assert (rtn == -1 );
70
101
assert (errno == EEXIST );
71
102
errno = 0 ;
103
+ }
72
104
73
- printf ( "\nsymlink/normal\n" );
74
- ret = symlink ("new-nonexistent-path" , "folder /link" );
75
- assert (ret == 0 );
105
+ void test_creating_symlink () {
106
+ int rtn = symlink ("new-nonexistent-path" , "directory /link" );
107
+ assert (rtn == 0 );
76
108
assert (errno == 0 );
77
109
errno = 0 ;
78
110
79
- printf ( "\nreadlink(created link)\n" ) ;
80
- ret = readlink ("folder /link" , buffer , 256 );
111
+ char buffer [ 256 ] = { 0 } ;
112
+ rtn = readlink ("directory /link" , buffer , 256 );
81
113
assert (errno == 0 );
82
114
#if !defined(__EMSCRIPTEN__ ) || defined(WASMFS )
83
115
assert (strcmp (buffer , "new-nonexistent-path" ) == 0 );
84
116
#else
85
- assert (strcmp (buffer , "/working/folder /new-nonexistent-path" ) == 0 );
117
+ assert (strcmp (buffer , "/working/directory /new-nonexistent-path" ) == 0 );
86
118
#endif
87
- assert (strlen (buffer ) == ret );
119
+ assert (strlen (buffer ) == rtn );
88
120
errno = 0 ;
121
+ }
89
122
123
+ void test_reading_shortened_symlink () {
124
+ char buffer [256 ] = {0 };
125
+ readlink ("directory/link" , buffer , 256 );
90
126
buffer [0 ] = buffer [1 ] = buffer [2 ] = buffer [3 ] = buffer [4 ] = buffer [5 ] = '*' ;
91
- printf ("\nreadlink(short buffer)\n" );
92
- ret = readlink ("link" , buffer , 4 );
127
+ int rtn = readlink ("link" , buffer , 4 );
93
128
assert (errno == 0 );
94
- assert (ret == 4 );
129
+ assert (rtn == 4 );
95
130
#if !defined(__EMSCRIPTEN__ ) || defined(WASMFS )
96
131
assert (strcmp (buffer , "../t**nexistent-path" ) == 0 );
97
132
#else
98
- assert (strcmp (buffer , "/the**ng/folder /new-nonexistent-path" ) == 0 );
133
+ assert (strcmp (buffer , "/the**ng/directory /new-nonexistent-path" ) == 0 );
99
134
#endif
100
135
errno = 0 ;
136
+ }
101
137
138
+ void test_noticing_loop_in_symlink () {
102
139
// FS.lookupPath should notice the symlink loop and return ELOOP, not go into
103
140
// an infinite recurse.
104
141
//
105
142
// This test doesn't work in wasmfs -- probably because access sees the
106
143
// symlink and returns true without bothering to chase the symlink
107
- symlink ("./linkX /inside" , "./linkX " );
108
- ret = access ("linkX " , F_OK );
109
- assert (ret == -1 );
144
+ symlink ("./loop-link /inside" , "./loop-link " );
145
+ int rtn = access ("loop-link " , F_OK );
146
+ assert (rtn == -1 );
110
147
assert (errno == ELOOP );
111
148
errno = 0 ;
149
+ }
150
+
151
+
152
+ void test_relative_path_symlinks () {
153
+ char * parents [] = {
154
+ "/working/directory/" ,
155
+ "/working/directory/subdirectory/" ,
156
+ "/working/"
157
+ };
112
158
159
+ char * links [] = {
160
+ "relative" ,
161
+ "subrelative" ,
162
+ "subdirectoryrelative" ,
163
+ };
164
+
165
+ for (int i = 0 ; i < sizeof links / sizeof links [0 ]; i ++ ) {
166
+ int rtn = chdir (parents [i ]);
167
+ assert (rtn == 0 );
168
+ char symlink [256 ] = {0 };
169
+ strcat (strcpy (symlink , parents [i ]), links [i ]);
170
+ printf ("symlink: '%s'\n" , symlink );
171
+ char buf [256 ] = {0 };
172
+ rtn = readlink (links [i ], buf , 256 );
173
+ FILE * fd = fopen (buf , "r" );
174
+ assert (fd );
175
+ char buffer [13 ] = {0 };
176
+ rtn = fread (buffer , 1 , 13 , fd );
177
+ assert (rtn <= 13 );
178
+ printf ("buffer: '%s'\n\n" , buffer );
179
+ fclose (fd );
180
+ }
181
+ }
182
+
183
+ void test_absolute_path_symlinks () {
184
+ char * links [] = {
185
+ "/working/directory/absolute" ,
186
+ "/working/directory/subdirectory/subabsolute" ,
187
+ "/working/subdirectoryabsolute"
188
+ };
189
+
190
+ for (int i = 0 ; i < sizeof links / sizeof links [0 ]; i ++ ) {
191
+ printf ("symlink: '%s'\n" , links [i ]);
192
+ char buf [256 ] = {0 };
193
+ readlink (links [i ], buf , 256 );
194
+ FILE * fd = fopen (buf , "r" );
195
+ assert (fd );
196
+ char buffer [13 ] = {0 };
197
+ int rtn = fread (buffer , 1 , 13 , fd );
198
+ assert (rtn <= 13 );
199
+ printf ("buffer: '%s'\n\n" , buffer );
200
+ fclose (fd );
201
+ }
202
+ }
203
+
204
+ int main () {
205
+ setup ();
206
+ test_reading_existing_symlinks ();
207
+ test_overwriting_symlink ();
208
+ test_creating_symlink ();
209
+ test_reading_shortened_symlink ();
210
+ test_noticing_loop_in_symlink ();
211
+ test_relative_path_symlinks ();
212
+ test_absolute_path_symlinks ();
113
213
return 0 ;
114
214
}
0 commit comments