1-module(file_name_SUITE).
2%%
3%% %CopyrightBegin%
4%%
5%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
6%%
7%% Licensed under the Apache License, Version 2.0 (the "License");
8%% you may not use this file except in compliance with the License.
9%% You may obtain a copy of the License at
10%%
11%%     http://www.apache.org/licenses/LICENSE-2.0
12%%
13%% Unless required by applicable law or agreed to in writing, software
14%% distributed under the License is distributed on an "AS IS" BASIS,
15%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16%% See the License for the specific language governing permissions and
17%% limitations under the License.
18%%
19%% %CopyrightEnd%
20%%
21
22-include_lib("common_test/include/ct.hrl").
23-include_lib("kernel/include/file.hrl").
24
25%%
26%% File operations that take filenames as parameters (* not prim_file operation) (** a drive):
27%% altname
28%% copy (*)
29%% del_dir
30%% delete
31%% get_cwd (**)
32%% list_dir
33%% make_dir
34%% make_link
35%% make_symlink
36%% open
37%% read_file
38%% read_file_info
39%% read_link
40%% read_link_info
41%% rename
42%% set_cwd
43%% write_file
44%% write_file_info
45%%
46%% File operations that opens/uses separate driver port (not connected to file)
47%% altname
48%% del_dir
49%% delete
50%% get_cwd
51%% list_dir
52%% make_dir
53%% make_link
54%% make_symlink
55%% read_file_info
56%% read_link
57%% read_link_info
58%% rename
59%% set_cwd
60%% write_file_info
61%%
62%% Operations that use ?FD_DRV in prim_file
63%% open
64%% read_file
65%% write_file
66%%
67%%
68%% Operations that return a filename/path
69%% altname
70%% get_cwd
71%% list_dir
72%% read_link
73
74-export([all/0,groups/0,suite/0,
75	 init_per_suite/1,end_per_suite/1,
76	 init_per_group/2,end_per_group/2,
77	 init_per_testcase/2, end_per_testcase/2]).
78-export([normal/1,icky/1,very_icky/1,normalize/1,home_dir/1]).
79
80-define(PRIM_FILE, prim_file).
81
82init_per_testcase(_Func, Config) ->
83    Config.
84
85end_per_testcase(_Func, _Config) ->
86    ok.
87
88suite() ->
89    [{ct_hooks,[ts_install_cth]},
90     {timetrap,{minutes,1}}].
91
92all() ->
93    [normal, icky, very_icky, normalize, home_dir].
94
95groups() ->
96    [].
97
98init_per_suite(Config) ->
99    Config.
100
101end_per_suite(_Config) ->
102    ok.
103
104init_per_group(_GroupName, Config) ->
105    Config.
106
107end_per_group(_GroupName, Config) ->
108    Config.
109
110%% Check that Erlang can be started with unicode named home directory.
111home_dir(Config) when is_list(Config) ->
112    try
113	Name=[960,945,964,961,953,954],
114	Priv = proplists:get_value(priv_dir, Config),
115	UniMode = file:native_name_encoding() =/= latin1,
116	if
117	    not UniMode ->
118		throw(need_unicode_mode);
119	    true ->
120		ok
121	end,
122	NewHome=filename:join(Priv,Name),
123	file:make_dir(NewHome),
124	{SaveOldName,SaveOldValue} = case os:type() of
125					 {win32,nt} ->
126					     HomePath=re:replace(filename:nativename(NewHome),"^[a-zA-Z]:","",[{return,list},unicode]),
127					     Save = os:getenv("HOMEPATH"),
128					     os:putenv("HOMEPATH",HomePath),
129					     {"HOMEPATH",Save};
130					 {unix,_} ->
131					     Save = os:getenv("HOME"),
132					     os:putenv("HOME",NewHome),
133					     {"HOME",Save};
134					 _ ->
135					     rm_rf(?PRIM_FILE,NewHome),
136					     throw(unsupported_os)
137				     end,
138	try
139	    {ok,Node} = test_server:start_node(test_unicode_homedir,slave,[{args,"-setcookie "++atom_to_list(erlang:get_cookie())}]),
140	    test_server:stop_node(Node),
141	    ok
142	after
143	    case SaveOldValue of
144		false ->
145		    os:unsetenv(SaveOldName);
146		_ ->
147		    os:putenv(SaveOldName,SaveOldValue)
148	    end,
149	    rm_rf(?PRIM_FILE,NewHome)
150	end
151    catch
152	throw:need_unicode_mode ->
153	    io:format("Sorry, can only run in unicode mode.~n"),
154	    {skipped,"VM needs to be started in Unicode filename mode"};
155	throw:unsupported_os ->
156	    io:format("Sorry, can only run on Unix/Windows.~n"),
157	    {skipped,"Runs only on Unix/Windows"}
158    end.
159
160%% Check that filename normalization works.
161normalize(Config) when is_list(Config) ->
162    rand:seed(exsplus, {1290,431421,830412}),
163    try
164	UniMode = file:native_name_encoding() =/= latin1,
165	if
166	    not UniMode ->
167		throw(need_unicode_mode);
168	    true ->
169		ok
170	end,
171	Pairs = [rand_comp_decomp(200) || _ <- lists:seq(1,1000)],
172	case os:type() of
173	    {unix,darwin} ->
174		[ true = (A =:= prim_file:internal_native2name(B)) ||
175		    {A,B} <- Pairs ];
176	    _ ->
177		ok
178	end,
179	[ true = (A =:= prim_file:internal_normalize_utf8(B)) ||
180	    {A,B} <- Pairs ]
181
182    catch
183	throw:need_unicode_mode ->
184	    io:format("Sorry, can only run in unicode mode.~n"),
185	    {skipped,"VM needs to be started in Unicode filename mode"}
186    end.
187
188%% Check file operations on normal file names regardless of unicode mode.
189normal(Config) when is_list(Config) ->
190    {ok,Dir} = file:get_cwd(),
191    try
192	Priv = proplists:get_value(priv_dir, Config),
193	file:set_cwd(Priv),
194	ok = check_normal(?PRIM_FILE),
195	ok = check_normal(file),
196	%% If all is good, delete dir again (avoid hanging dir on windows)
197	rm_rf(file,"normal_dir"),
198	ok
199    after
200	file:set_cwd(Dir)
201    end.
202
203
204%% Check file operations on normal file names regardless of unicode mode.
205icky(Config) when is_list(Config) ->
206    case hopeless_darwin() of
207	true ->
208	    {skipped,"This version of darwin does not support icky names at all."};
209	false ->
210	    {ok,Dir} = file:get_cwd(),
211	    try
212		Priv = proplists:get_value(priv_dir, Config),
213		file:set_cwd(Priv),
214		ok = check_icky(?PRIM_FILE),
215		ok = check_icky(file),
216		%% If all is good, delete dir again (avoid hanging dir on windows)
217		rm_rf(file,"icky_dir"),
218		ok
219	    after
220		file:set_cwd(Dir)
221	    end
222    end.
223%% Check file operations on normal file names regardless of unicode mode.
224very_icky(Config) when is_list(Config) ->
225    case hopeless_darwin() of
226	true ->
227	    {skipped,"This version of darwin does not support icky names at all."};
228	false ->
229	    {ok,Dir} = file:get_cwd(),
230	    try
231		Priv = proplists:get_value(priv_dir, Config),
232		file:set_cwd(Priv),
233		case check_very_icky(?PRIM_FILE) of
234		    need_unicode_mode ->
235			{skipped,"VM needs to be started in Unicode filename mode"};
236		    ok ->
237			ok = check_very_icky(file),
238			%% If all is good, delete dir again
239			%% (avoid hanging dir on windows)
240			rm_rf(file,"very_icky_dir"),
241			ok
242		end
243	    after
244		file:set_cwd(Dir)
245	    end
246    end.
247
248
249check_normal(Mod) ->
250    {ok,Dir} = Mod:get_cwd(),
251    try
252	NormalDir = make_normal_dir(Mod, "normal_dir"),
253	io:format("Normaldir = ~p\n", [NormalDir]),
254	L1 = lists:sort(list(NormalDir)),
255	{ok, L0} = Mod:list_dir("."),
256	io:format("L0 = ~p\n", [L0]),
257	L1 = lists:sort(L0),
258	{ok,D2} = Mod:get_cwd(),
259	true = is_list(D2),
260	case Mod:altname("fil1") of
261	    {error,enotsup} ->
262		ok;
263	    {ok,LLL} when is_list(LLL) ->
264		ok
265	end,
266	[ true = is_list(El) || El <- L1],
267	Syms = [ {S,Targ,list_to_binary(get_data(Targ, NormalDir))}
268		 || {T,S,Targ} <- NormalDir, T =:= symlink ],
269	[ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
270	[ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
271
272	{ok,BeginAt} = Mod:get_cwd(),
273	true = is_list(BeginAt),
274	TempDir = "temp_dir",
275	make_normal_dir(Mod, TempDir),
276	{error,enoent} = Mod:set_cwd("tmp_dir"),
277	{ok, NowAt} = Mod:get_cwd(),
278	true = BeginAt =/= NowAt,
279	ok = Mod:set_cwd(".."),
280	{ok,BeginAt} = Mod:get_cwd(),
281	rm_r(Mod, TempDir),
282	true = is_list(Dir),
283	[ true = is_list(FN) || FN <- L0 ],
284	case Mod:make_link("fil1","nisse") of
285	    ok ->
286		{ok, <<"fil1">>} = Mod:read_file("nisse"),
287		{ok, #file_info{type = regular}} = Mod:read_link_info("nisse"),
288		ok = Mod:delete("nisse"),
289		{ok, <<"fil1">>} = Mod:read_file("fil1"),
290		{error,enoent} = Mod:read_file("nisse"),
291		{error,enoent} = Mod:read_link_info("nisse");
292	    {error,enotsup} ->
293		ok
294	end,
295	[ begin
296	      {ok, FD} = Mod:open(Name,[read,binary]),
297	      BC = list_to_binary(Content),
298	      {ok, BC} = Mod:read(FD,1024),
299	      ok = file:close(FD)
300	  end || {regular,Name,Content} <- NormalDir ],
301	{error, badarg} = Mod:rename("fil1\0tmp_fil2","tmp_fil1"),
302	Mod:rename("fil1","tmp_fil1"),
303	{error, badarg} = Mod:read_file("tmp_fil1\0.txt"),
304	{ok, <<"fil1">>} = Mod:read_file("tmp_fil1"),
305	{error,enoent} = Mod:read_file("fil1"),
306	Mod:rename("tmp_fil1","fil1"),
307	{ok, <<"fil1">>} = Mod:read_file("fil1"),
308	{error,enoent} = Mod:read_file("tmp_fil1"),
309	{ok,FI} = Mod:read_file_info("fil1"),
310	NewMode = FI#file_info.mode band (bnot 8#333),
311	NewMode2 = NewMode bor 8#222,
312	true = NewMode2 =/= NewMode,
313	ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode}),
314	{ok,#file_info{mode = NewMode}} = Mod:read_file_info("fil1"),
315	ok = Mod:write_file_info("fil1",FI#file_info{mode = NewMode2}),
316	{ok,#file_info{mode = NewMode2}} = Mod:read_file_info("fil1"),
317	ok
318    after
319        case Mod:read_file_info("fil1") of
320	    {ok,FII} ->
321		NewModeI = FII#file_info.mode bor 8#777,
322		Mod:write_file_info("fil1",FII#file_info{mode = NewModeI});
323	    _ ->
324		ok
325	end,
326	Mod:set_cwd(Dir),
327        io:format("Wd now: ~s~n",[Dir])
328    end.
329
330check_icky(Mod) ->
331    {ok,Dir} = Mod:get_cwd(),
332    try
333	true=(length("åäö") =:= 3),
334	UniMode = file:native_name_encoding() =/= latin1,
335	IckyDir = make_icky_dir(Mod, "icky_dir"),
336 	{ok, L0} = Mod:list_dir_all("."),
337	L1 = lists:sort(L0),
338	io:format("~p~n~p~n~n",[L1,lists:sort(list(IckyDir))]),
339	L1 = lists:sort(convlist(list(IckyDir))),
340	{ok,D2} = Mod:get_cwd(),
341	true = is_list(D2),
342	%% Altname only on windows, and there are no non native filenames there
343	%% 	case Mod:altname("fil1") of
344	%% 	    {error,enotsup} ->
345	%% 		ok;
346	%% 	    {ok,LLL} when is_list(LLL) ->
347	%% 		ok
348	%% 	end,
349	[ true = ((is_list(El) or (UniMode and is_binary(El))))  || El <- L1],
350	Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,IckyDir))}
351		 || {T,S,Targ} <- IckyDir, T =:= symlink ],
352	[ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
353 	[ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
354	    {SymL,Targ,_} <- Syms ],
355
356	{ok,BeginAt} = Mod:get_cwd(),
357	true = is_list(BeginAt),
358        _ = make_icky_dir(Mod, "åäö_dir"),
359        {error,enoent} = Mod:set_cwd("åä_dir"),
360	{ok, NowAt} = Mod:get_cwd(),
361	true = is_list(NowAt),
362	true = BeginAt =/= NowAt,
363	ok = Mod:set_cwd(".."),
364	{ok,BeginAt} = Mod:get_cwd(),
365        rm_r2(Mod,"åäö_dir"),
366	{OS,_} = os:type(),
367
368	%% Check that treat_icky really converts to the same as the OS
369	case UniMode of
370	    true ->
371		ok = Mod:make_dir("åäö_dir"),
372		ok = Mod:set_cwd("åäö_dir"),
373		ok = Mod:write_file(<<"ååå">>,<<"hello">>),
374		Treated = treat_icky(<<"ååå">>),
375		{ok,[Treated]} = Mod:list_dir_all("."),
376		ok = Mod:delete(<<"ååå">>),
377		{ok,[]} = Mod:list_dir("."),
378		ok = Mod:set_cwd(".."),
379		rm_r2(Mod,"åäö_dir");
380	    false ->
381		ok
382	end,
383
384	_ = make_icky_dir(Mod, treat_icky(<<"åäö_dir"/utf8>>)),
385	if
386	    UniMode and (OS =/= win32) ->
387		{error,enoent} = Mod:set_cwd("åäö_dir");
388	    true ->
389		ok
390	end,
391	ok = Mod:set_cwd(".."),
392	{ok,BeginAt} = Mod:get_cwd(),
393	case Mod:make_link("fil1", "nisseö") of
394	    ok ->
395		{ok, <<"fil1">>} = Mod:read_file("nisseö"),
396		{ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"),
397		ok = Mod:delete("nisseö"),
398		ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)),
399		{ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)),
400		{ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)),
401		ok = Mod:delete(treat_icky(<<"nisseö">>)),
402		{ok, <<"fil1">>} = Mod:read_file("fil1"),
403		{error,enoent} = Mod:read_file("nisseö"),
404		{error,enoent} = Mod:read_link_info("nisseö"),
405		{error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)),
406		{error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>));
407	    {error,enotsup} ->
408		ok
409	end,
410	[ begin
411	      {ok, FD} = Mod:open(Name,[read,binary]),
412	      BC = list_to_binary([Content]),
413	      {ok, BC} = Mod:read(FD,1024),
414	      ok = file:close(FD)
415	  end || {regular,Name,Content} <- IckyDir ],
416        Mod:rename("åäö2","åäö_fil1"),
417        {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"),
418        {error,enoent} = Mod:read_file("åäö2"),
419        Mod:rename("åäö_fil1","åäö2"),
420        {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
421        {error,enoent} = Mod:read_file("åäö_fil1"),
422
423        Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)),
424        {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
425	if
426	    UniMode and (OS =/= win32) ->
427		{error,enoent} = Mod:read_file("åäö_fil1");
428	    true ->
429		ok
430	end,
431        {error,enoent} = Mod:read_file("åäö2"),
432        Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"),
433        {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
434        {error,enoent} = Mod:read_file("åäö_fil1"),
435        {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
436
437        {ok,FI} = Mod:read_file_info("åäö2"),
438	NewMode = FI#file_info.mode band (bnot 8#333),
439	NewMode2 = NewMode bor 8#222,
440	true = NewMode2 =/= NewMode,
441        ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}),
442        {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"),
443        ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}),
444        {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"),
445
446        {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
447	true = NewMode2 =/= NewMode,
448        ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}),
449        {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
450        ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}),
451        {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
452	ok
453    after
454	Mod:set_cwd(Dir),
455        io:format("Wd now: ~s~n",[Dir])
456    end.
457
458check_very_icky(Mod) ->
459    {ok,Dir} = Mod:get_cwd(),
460    try
461	true=(length("åäö") =:= 3),
462	UniMode = file:native_name_encoding() =/= latin1,
463	if
464	    not UniMode ->
465		throw(need_unicode_mode);
466	    true ->
467		ok
468	end,
469	VeryIckyDir = make_very_icky_dir(Mod, "very_icky_dir"),
470	Expected = lists:sort(convlist(list(VeryIckyDir))),
471	{ok, Actual} = Mod:list_dir_all("."),
472	Expected = lists:sort(Actual),
473	{ok,D2} = Mod:get_cwd(),
474	true = is_list(D2),
475	[ true = ((is_list(El) or is_binary(El)))  || El <- Expected],
476	Syms = [{S,conv(Targ),list_to_binary(get_data(Targ, VeryIckyDir))}
477		|| {symlink,S,Targ} <- VeryIckyDir],
478	[ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
479	[ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
480	    {SymL,Targ,_} <- Syms ],
481
482	{ok,BeginAt} = Mod:get_cwd(),
483	OtherDir = [1088,1079,1091] ++ "_dir",
484	true = is_list(BeginAt),
485	make_very_icky_dir(Mod, OtherDir),
486        {error,enoent} = Mod:set_cwd("åä_dir"),
487	{ok, NowAt} = Mod:get_cwd(),
488	true = is_list(NowAt),
489	true = BeginAt =/= NowAt,
490	ok = Mod:set_cwd(".."),
491	{ok,BeginAt} = Mod:get_cwd(),
492	rm_r2(Mod, OtherDir),
493
494	case Mod:make_link("fil1","nisse"++[1088,1079,1091]) of
495	    ok ->
496		{ok, <<"fil1">>} =
497		    Mod:read_file("nisse"++[1088,1079,1091]),
498		{ok, #file_info{type = regular}} =
499		    Mod:read_link_info("nisse"++[1088,1079,1091]),
500		ok = Mod:delete("nisse"++[1088,1079,1091]),
501		ok = Mod:make_link("fil1",<<"nisseö">>),
502		{ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>),
503		{ok, #file_info{type = regular}} =
504		    Mod:read_link_info(<<"nisseö">>),
505		ok = Mod:delete(<<"nisseö">>),
506		{ok, <<"fil1">>} = Mod:read_file("fil1"),
507		{error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]),
508		{error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]),
509		{error,enoent} = Mod:read_file(<<"nisseö">>),
510		{error,enoent} = Mod:read_link_info(<<"nisseö">>);
511	    {error,enotsup} ->
512		ok
513	end,
514	[ begin
515	      {ok, FD} = Mod:open(Name,[read,binary]),
516	      BC = list_to_binary([Content]),
517	      {ok, BC} = Mod:read(FD,1024),
518	      ok = file:close(FD)
519	  end || {regular,Name,Content} <- VeryIckyDir ],
520	Mod:rename([956,965,963,954,959,49],
521		   [956,965,963,954,959]++"_fil1"),
522        {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
523	{error,enoent} = Mod:read_file([956,965,963,954,959,49]),
524	Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]),
525        {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]),
526	{error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"),
527
528	{ok,FI} = Mod:read_file_info([956,965,963,954,959,49]),
529	NewMode = FI#file_info.mode band (bnot 8#333),
530	NewMode2 = NewMode bor 8#222,
531	true = NewMode2 =/= NewMode,
532	ok = Mod:write_file_info([956,965,963,954,959,49],
533				 FI#file_info{mode = NewMode}),
534	{ok,#file_info{mode = NewMode}} =
535	    Mod:read_file_info([956,965,963,954,959,49]),
536	ok = Mod:write_file_info([956,965,963,954,959,49],
537				 FI#file_info{mode = NewMode2}),
538	{ok,#file_info{mode = NewMode2}} =
539	    Mod:read_file_info([956,965,963,954,959,49]),
540	ok
541    catch
542	throw:need_unicode_mode ->
543	    io:format("Sorry, can only run in unicode mode.~n"),
544	    need_unicode_mode
545    after
546	Mod:set_cwd(Dir),
547        io:format("Wd now: ~s~n",[Dir])
548    end.
549
550%%
551%% Utilities
552%%
553
554
555rm_rf(Mod,Dir) ->
556    case  Mod:read_link_info(Dir) of
557	{ok, #file_info{type = directory}} ->
558	    {ok, Content} = Mod:list_dir_all(Dir),
559	    [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ],
560	    Mod:del_dir(Dir),
561	    ok;
562	{ok, #file_info{}} ->
563	    Mod:delete(Dir);
564	_ ->
565	    ok
566    end.
567
568rm_r(Mod,Dir) ->
569    case  Mod:read_link_info(Dir) of
570	{ok, #file_info{type = directory}} ->
571	    {ok,#file_info{type = directory}} =  Mod:read_file_info(Dir),
572	    {ok, Content} = Mod:list_dir_all(Dir),
573	    [ true = is_list(Part) || Part <- Content ],
574	    [ true = is_list(filename:join(Dir,Part)) || Part <- Content ],
575	    [ rm_r(Mod,filename:join(Dir,C)) || C <- Content ],
576	    ok = Mod:del_dir(Dir),
577	    ok;
578	{ok, #file_info{type = regular}} ->
579	    {ok,#file_info{type = regular}} =  Mod:read_file_info(Dir),
580	    ok = Mod:delete(Dir);
581	{ok, #file_info{type = symlink}} ->
582	    ok = Mod:delete(Dir)
583    end.
584%% For icky test, allow binaries sometimes
585rm_r2(Mod,Dir) ->
586    %% erlang:display({rm_r2,Dir}),
587    case  Mod:read_link_info(Dir) of
588	{ok, #file_info{type = directory}} ->
589	    {ok,#file_info{type = directory}} =  Mod:read_file_info(Dir),
590	    {ok, Content} = Mod:list_dir_all(Dir),
591	    UniMode = file:native_name_encoding() =/= latin1,
592	    [ true = (is_list(Part) orelse UniMode) || Part <- Content ],
593	    [ true = (is_list(filename:join(Dir,Part)) orelse UniMode) || Part <- Content ],
594	    [ rm_r2(Mod,filename:join(Dir,C)) || C <- Content ],
595	    ok = Mod:del_dir(Dir),
596	    ok;
597	{ok, #file_info{type = regular}} ->
598	    {ok,#file_info{type = regular}} =  Mod:read_file_info(Dir),
599	    ok = Mod:delete(Dir);
600	{ok, #file_info{type = symlink}} ->
601	    ok = Mod:delete(Dir)
602    end.
603
604make_normal_dir(Mod, DirName) ->
605    Dir = [{regular,"fil1","fil1"},
606	   {regular,"fil2","fil2"},
607	   {hardlink,"fil3","fil2"},
608	   {symlink,"fil4","fil2"},
609	   {directory,"subdir",
610	    [{regular,"subfil1","subfil1"}]}],
611    rm_rf(Mod, DirName),
612    Mod:make_dir(DirName),
613    Mod:set_cwd(DirName),
614    make_dir_contents(Dir, Mod).
615
616make_icky_dir(Mod, IckyDirName) ->
617    Icky = [{regular,"fil1","fil1"},
618	    {regular,"åäö2","åäö2"},
619	    {hardlink,"åäö3","åäö2"},
620	    {symlink,"åäö4","åäö2"},
621	    {regular,treat_icky(<<"åäö5">>),"åäö5"},
622	    {symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)},
623	    {directory,treat_icky(<<"åäösubdir2">>),
624	     [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
625	      {regular,"åäösubfil3","åäösubfil13"}]},
626	    {directory,"åäösubdir",
627	     [{regular,"åäösubfil1","åäösubfil1"}]}],
628    rm_rf(Mod, IckyDirName),
629    ok = Mod:make_dir(IckyDirName),
630    ok = Mod:set_cwd(IckyDirName),
631    make_dir_contents(Icky, Mod).
632
633hopeless_darwin() ->
634    case {os:type(),os:version()} of
635        {{unix,darwin},{Major,_,_}} ->
636            %% icky file names worked between 10 and 17, but started returning
637            %% EILSEQ in 18. The check against 18 is exact in case newer
638            %% versions of Darwin support them again.
639            Major < 9 orelse Major =:= 18;
640        _ ->
641            false
642    end.
643
644make_very_icky_dir(Mod, DirName) ->
645    Desc = [{regular,"fil1","fil1"},
646	    {regular,[956,965,963,954,959,49],"åäö2"},
647	    {hardlink,[956,965,963,954,959,50],
648	     [956,965,963,954,959,49],
649	     "åäö2"},
650	    {symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]},
651	    {regular,treat_icky(<<"åäö5">>),"åäö5"},
652	    {symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)},
653	    {directory,treat_icky(<<"åäösubdir2">>),
654	     [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
655	      {regular,"åäösubfil3","åäösubfil13"}]},
656	    {directory,[956,965,963,954,959]++"subdir1",
657	     [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}],
658    rm_rf(Mod, DirName),
659    ok = Mod:make_dir(DirName),
660    ok = Mod:set_cwd(DirName),
661    make_dir_contents(Desc, Mod).
662
663%% Some OS'es simply do not allow non UTF8 filenames
664treat_icky(Bin) ->
665    case os:type() of
666	{unix,darwin} ->
667	    binary_to_list(procentify(Bin));
668	{win32,_} ->
669	    binary_to_list(Bin);
670	_ ->
671	    Bin
672    end.
673
674%% Handle windows having absolute soft link targets.
675fixlink({ok,Link}) ->
676    case os:type() of
677	{win32,_} ->
678	    {ok,filename:basename(Link)};
679	_ ->
680	    {ok,Link}
681    end;
682fixlink(X) ->
683    X.
684
685procentify(<<>>) ->
686    <<>>;
687procentify(<<X:8,Rst/binary>>) when X > 127 ->
688    T=procentify(Rst),
689    Y = list_to_binary([$%
690			| io_lib:format("~2.16B",[X])]),
691    <<Y/binary,T/binary>>;
692procentify(<<X:8,Rst/binary>>) ->
693    T=procentify(Rst),
694    <<X:8,T/binary>>.
695
696
697list([]) ->
698    [];
699list([{_,Name,_} | T]) ->
700    [Name | list(T)].
701
702
703get_data(FN,List) ->
704    case lists:keysearch(FN,2,List) of
705	{value,{regular,FN,C}} ->
706	    C;
707	{value,{symlink,FN,NewFN}} ->
708	    get_data(NewFN,List);
709	_->
710	    []
711    end.
712
713
714convlist(L) ->
715    convlist(file:native_name_encoding(),L).
716convlist(latin1,[Bin|T]) when is_binary(Bin) ->
717    %% erlang:display('Convert...'),
718    [binary_to_list(Bin)| convlist(latin1,T)];
719convlist(Any,[H|T]) ->
720    [H|convlist(Any,T)];
721convlist(_,[]) ->
722    [].
723
724conv(L) ->
725    NoUniMode = file:native_name_encoding() =:= latin1,
726    if
727	NoUniMode, is_binary(L) ->
728	    binary_to_list(L);
729	true ->
730	    L
731    end.
732
733
734make_dir_contents([{regular,Name,Contents}=H|T], Mod) ->
735    ok = Mod:write_file(Name, Contents),
736    [H|make_dir_contents(T, Mod)];
737make_dir_contents([{hardlink,Target,Name}|T], Mod) ->
738    case Mod:make_link(Name, Target) of
739	ok ->
740	    [{regular,Target,Name}|make_dir_contents(T, Mod)];
741	{error,enotsup} ->
742	    make_dir_contents(T, Mod)
743    end;
744make_dir_contents([{hardlink,Target,Name,Contents}|T], Mod) ->
745    case Mod:make_link(Name, Target) of
746	ok ->
747	    [{regular,Target,Contents}|make_dir_contents(T, Mod)];
748	{error,enotsup} ->
749	    make_dir_contents(T, Mod)
750    end;
751make_dir_contents([{symlink,Target,Name}=H|T], Mod) ->
752    case Mod:make_symlink(Name, Target) of
753	ok ->
754	    [H|make_dir_contents(T, Mod)];
755	{error,enotsup} ->
756	    make_dir_contents(T, Mod);
757	{error,eperm} ->
758	    make_dir_contents(T, Mod)
759    end;
760make_dir_contents([{directory,Dir,C0}|T], Mod) ->
761    ok = Mod:make_dir(Dir),
762    C1 = [case Op of
763	      Link when Link =:= hardlink; Link =:= symlink ->
764		  {Op,filename:join(Dir, Name0),filename:join(Dir, Extra)};
765	      _ ->
766		  {Op,filename:join(Dir, Name0),Extra}
767	  end || {Op,Name0,Extra} <- C0],
768    C2 = make_dir_contents(C1, Mod),
769    C = [{Op,filename:basename(Name0),Extra} ||
770	    {Op,Name0,Extra} <- C2],
771    [{directory,Dir,C}|make_dir_contents(T, Mod)];
772make_dir_contents([], _Mod) ->
773    [].
774
775
776rand_comp_decomp(Max) ->
777    N = rand:uniform(Max),
778    L = [ rand_decomp() || _ <- lists:seq(1,N) ],
779    LC = [ A || {A,_} <- L],
780    LD = lists:flatten([B || {_,B} <- L]),
781    LB = unicode:characters_to_binary(LD,unicode,utf8),
782    {LC,LB}.
783
784rand_decomp() ->
785    BT = bigtup(),
786    SZ = tuple_size(BT),
787    element(rand:uniform(SZ),BT).
788bigtup() ->
789    {{192,[65,768]},
790     {200,[69,768]},
791     {204,[73,768]},
792     {210,[79,768]},
793     {217,[85,768]},
794     {7808,[87,768]},
795     {7922,[89,768]},
796     {224,[97,768]},
797     {232,[101,768]},
798     {236,[105,768]},
799     {242,[111,768]},
800     {249,[117,768]},
801     {7809,[119,768]},
802     {7923,[121,768]},
803     {8173,[168,768]},
804     {7846,[65,770,768]},
805     {7872,[69,770,768]},
806     {7890,[79,770,768]},
807     {7847,[97,770,768]},
808     {7873,[101,770,768]},
809     {7891,[111,770,768]},
810     {7700,[69,772,768]},
811     {7760,[79,772,768]},
812     {7701,[101,772,768]},
813     {7761,[111,772,768]},
814     {7856,[65,774,768]},
815     {7857,[97,774,768]},
816     {475,[85,776,768]},
817     {476,[117,776,768]},
818     {8146,[953,776,768]},
819     {8162,[965,776,768]},
820     {8074,[913,837,787,768]},
821     {8090,[919,837,787,768]},
822     {8106,[937,837,787,768]},
823     {8066,[945,837,787,768]},
824     {8082,[951,837,787,768]},
825     {8098,[969,837,787,768]},
826     {7946,[913,787,768]},
827     {7962,[917,787,768]},
828     {7978,[919,787,768]},
829     {7994,[921,787,768]},
830     {8010,[927,787,768]},
831     {8042,[937,787,768]},
832     {7938,[945,787,768]},
833     {7954,[949,787,768]},
834     {7970,[951,787,768]},
835     {7986,[953,787,768]},
836     {8002,[959,787,768]},
837     {8018,[965,787,768]},
838     {8034,[969,787,768]},
839     {8075,[913,837,788,768]},
840     {8091,[919,837,788,768]},
841     {8107,[937,837,788,768]},
842     {8067,[945,837,788,768]},
843     {8083,[951,837,788,768]},
844     {8099,[969,837,788,768]},
845     {7947,[913,788,768]},
846     {7963,[917,788,768]},
847     {7979,[919,788,768]},
848     {7995,[921,788,768]},
849     {8011,[927,788,768]},
850     {8027,[933,788,768]},
851     {8043,[937,788,768]},
852     {7939,[945,788,768]},
853     {7955,[949,788,768]},
854     {7971,[951,788,768]},
855     {7987,[953,788,768]},
856     {8003,[959,788,768]},
857     {8019,[965,788,768]},
858     {8035,[969,788,768]},
859     {7900,[79,795,768]},
860     {7914,[85,795,768]},
861     {7901,[111,795,768]},
862     {7915,[117,795,768]},
863     {8114,[945,837,768]},
864     {8130,[951,837,768]},
865     {8178,[969,837,768]},
866     {8122,[913,768]},
867     {8136,[917,768]},
868     {8138,[919,768]},
869     {8154,[921,768]},
870     {8184,[927,768]},
871     {8170,[933,768]},
872     {8186,[937,768]},
873     {8048,[945,768]},
874     {8050,[949,768]},
875     {8052,[951,768]},
876     {8054,[953,768]},
877     {8056,[959,768]},
878     {8058,[965,768]},
879     {8060,[969,768]},
880     {8141,[8127,768]},
881     {8157,[8190,768]},
882     {193,[65,769]},
883     {262,[67,769]},
884     {201,[69,769]},
885     {500,[71,769]},
886     {205,[73,769]},
887     {7728,[75,769]},
888     {313,[76,769]},
889     {7742,[77,769]},
890     {323,[78,769]},
891     {211,[79,769]},
892     {7764,[80,769]},
893     {340,[82,769]},
894     {346,[83,769]},
895     {218,[85,769]},
896     {7810,[87,769]},
897     {221,[89,769]},
898     {377,[90,769]},
899     {225,[97,769]},
900     {263,[99,769]},
901     {233,[101,769]},
902     {501,[103,769]},
903     {237,[105,769]},
904     {7729,[107,769]},
905     {314,[108,769]},
906     {7743,[109,769]},
907     {324,[110,769]},
908     {243,[111,769]},
909     {7765,[112,769]},
910     {341,[114,769]},
911     {347,[115,769]},
912     {250,[117,769]},
913     {7811,[119,769]},
914     {253,[121,769]},
915     {378,[122,769]},
916     {8174,[168,769]},
917     {508,[198,769]},
918     {510,[216,769]},
919     {509,[230,769]},
920     {511,[248,769]},
921     {7844,[65,770,769]},
922     {7870,[69,770,769]},
923     {7888,[79,770,769]},
924     {7845,[97,770,769]},
925     {7871,[101,770,769]},
926     {7889,[111,770,769]},
927     {7756,[79,771,769]},
928     {7800,[85,771,769]},
929     {7757,[111,771,769]},
930     {7801,[117,771,769]},
931     {7702,[69,772,769]},
932     {7762,[79,772,769]},
933     {7703,[101,772,769]},
934     {7763,[111,772,769]},
935     {7854,[65,774,769]},
936     {7855,[97,774,769]},
937     {7726,[73,776,769]},
938     {471,[85,776,769]},
939     {7727,[105,776,769]},
940     {472,[117,776,769]},
941     {8147,[953,776,769]},
942     {8163,[965,776,769]},
943     {506,[65,778,769]},
944     {507,[97,778,769]},
945     {8076,[913,837,787,769]},
946     {8092,[919,837,787,769]},
947     {8108,[937,837,787,769]},
948     {8068,[945,837,787,769]},
949     {8084,[951,837,787,769]},
950     {8100,[969,837,787,769]},
951     {7948,[913,787,769]},
952     {7964,[917,787,769]},
953     {7980,[919,787,769]},
954     {7996,[921,787,769]},
955     {8012,[927,787,769]},
956     {8044,[937,787,769]},
957     {7940,[945,787,769]},
958     {7956,[949,787,769]},
959     {7972,[951,787,769]},
960     {7988,[953,787,769]},
961     {8004,[959,787,769]},
962     {8020,[965,787,769]},
963     {8036,[969,787,769]},
964     {8077,[913,837,788,769]},
965     {8093,[919,837,788,769]},
966     {8109,[937,837,788,769]},
967     {8069,[945,837,788,769]},
968     {8085,[951,837,788,769]},
969     {8101,[969,837,788,769]},
970     {7949,[913,788,769]},
971     {7965,[917,788,769]},
972     {7981,[919,788,769]},
973     {7997,[921,788,769]},
974     {8013,[927,788,769]},
975     {8029,[933,788,769]},
976     {8045,[937,788,769]},
977     {7941,[945,788,769]},
978     {7957,[949,788,769]},
979     {7973,[951,788,769]},
980     {7989,[953,788,769]},
981     {8005,[959,788,769]},
982     {8021,[965,788,769]},
983     {8037,[969,788,769]},
984     {7898,[79,795,769]},
985     {7912,[85,795,769]},
986     {7899,[111,795,769]},
987     {7913,[117,795,769]},
988     {7688,[67,807,769]},
989     {7689,[99,807,769]},
990     {8116,[945,837,769]},
991     {8132,[951,837,769]},
992     {8180,[959,837,769]},
993     {8123,[913,769]},
994     {8137,[917,769]},
995     {8139,[919,769]},
996     {8155,[921,769]},
997     {8185,[927,769]},
998     {8171,[933,769]},
999     {8187,[937,769]},
1000     {8049,[945,769]},
1001     {8051,[949,769]},
1002     {8053,[951,769]},
1003     {8055,[953,769]},
1004     {8057,[959,769]},
1005     {8059,[965,769]},
1006     {8061,[969,769]},
1007     {1027,[1043,769]},
1008     {1036,[1050,769]},
1009     {1107,[1075,769]},
1010     {1116,[1082,769]},
1011     {8142,[8127,769]},
1012     {8158,[8190,769]},
1013     {194,[65,770]},
1014     {264,[67,770]},
1015     {202,[69,770]},
1016     {284,[71,770]},
1017     {292,[72,770]},
1018     {206,[73,770]},
1019     {308,[74,770]},
1020     {212,[79,770]},
1021     {348,[83,770]},
1022     {219,[85,770]},
1023     {372,[87,770]},
1024     {374,[89,770]},
1025     {7824,[90,770]},
1026     {226,[97,770]},
1027     {265,[99,770]},
1028     {234,[101,770]},
1029     {285,[103,770]},
1030     {293,[104,770]},
1031     {238,[105,770]},
1032     {309,[106,770]},
1033     {244,[111,770]},
1034     {349,[115,770]},
1035     {251,[117,770]},
1036     {373,[119,770]},
1037     {375,[121,770]},
1038     {7825,[122,770]},
1039     {7852,[65,803,770]},
1040     {7878,[69,803,770]},
1041     {7896,[79,803,770]},
1042     {7853,[97,803,770]},
1043     {7879,[101,803,770]},
1044     {7897,[111,803,770]},
1045     {195,[65,771]},
1046     {7868,[69,771]},
1047     {296,[73,771]},
1048     {209,[78,771]},
1049     {213,[79,771]},
1050     {360,[85,771]},
1051     {7804,[86,771]},
1052     {7928,[89,771]},
1053     {227,[97,771]},
1054     {7869,[101,771]},
1055     {297,[105,771]},
1056     {241,[110,771]},
1057     {245,[111,771]},
1058     {361,[117,771]},
1059     {7805,[118,771]},
1060     {7929,[121,771]},
1061     {7850,[65,770,771]},
1062     {7876,[69,770,771]},
1063     {7894,[79,770,771]},
1064     {7851,[97,770,771]},
1065     {7877,[101,770,771]},
1066     {7895,[111,770,771]},
1067     {7860,[65,774,771]},
1068     {7861,[97,774,771]},
1069     {7904,[79,795,771]},
1070     {7918,[85,795,771]},
1071     {7905,[111,795,771]},
1072     {7919,[117,795,771]},
1073     {256,[65,772]},
1074     {274,[69,772]},
1075     {7712,[71,772]},
1076     {298,[73,772]},
1077     {332,[79,772]},
1078     {362,[85,772]},
1079     {257,[97,772]},
1080     {275,[101,772]},
1081     {7713,[103,772]},
1082     {299,[105,772]},
1083     {333,[111,772]},
1084     {363,[117,772]},
1085     {482,[198,772]},
1086     {483,[230,772]},
1087     {480,[65,775,772]},
1088     {481,[97,775,772]},
1089     {478,[65,776,772]},
1090     {469,[85,776,772]},
1091     {479,[97,776,772]},
1092     {470,[117,776,772]},
1093     {7736,[76,803,772]},
1094     {7772,[82,803,772]},
1095     {7737,[108,803,772]},
1096     {7773,[114,803,772]},
1097     {492,[79,808,772]},
1098     {493,[111,808,772]},
1099     {8121,[913,772]},
1100     {8153,[921,772]},
1101     {8169,[933,772]},
1102     {8113,[945,772]},
1103     {8145,[953,772]},
1104     {8161,[965,772]},
1105     {1250,[1048,772]},
1106     {1262,[1059,772]},
1107     {1251,[1080,772]},
1108     {1263,[1091,772]},
1109     {258,[65,774]},
1110     {276,[69,774]},
1111     {286,[71,774]},
1112     {300,[73,774]},
1113     {334,[79,774]},
1114     {364,[85,774]},
1115     {259,[97,774]},
1116     {277,[101,774]},
1117     {287,[103,774]},
1118     {301,[105,774]},
1119     {335,[111,774]},
1120     {365,[117,774]},
1121     {7862,[65,803,774]},
1122     {7863,[97,803,774]},
1123     {7708,[69,807,774]},
1124     {7709,[101,807,774]},
1125     {8120,[913,774]},
1126     {8152,[921,774]},
1127     {8168,[933,774]},
1128     {8112,[945,774]},
1129     {8144,[953,774]},
1130     {8160,[965,774]},
1131     {1232,[1040,774]},
1132     {1238,[1045,774]},
1133     {1217,[1046,774]},
1134     {1049,[1048,774]},
1135     {1038,[1059,774]},
1136     {1233,[1072,774]},
1137     {1239,[1077,774]},
1138     {1218,[1078,774]},
1139     {1081,[1080,774]},
1140     {1118,[1091,774]},
1141     {7682,[66,775]},
1142     {266,[67,775]},
1143     {7690,[68,775]},
1144     {278,[69,775]},
1145     {7710,[70,775]},
1146     {288,[71,775]},
1147     {7714,[72,775]},
1148     {304,[73,775]},
1149     {7744,[77,775]},
1150     {7748,[78,775]},
1151     {7766,[80,775]},
1152     {7768,[82,775]},
1153     {7776,[83,775]},
1154     {7786,[84,775]},
1155     {7814,[87,775]},
1156     {7818,[88,775]},
1157     {7822,[89,775]},
1158     {379,[90,775]},
1159     {7683,[98,775]},
1160     {267,[99,775]},
1161     {7691,[100,775]},
1162     {279,[101,775]},
1163     {7711,[102,775]},
1164     {289,[103,775]},
1165     {7715,[104,775]},
1166     {7745,[109,775]},
1167     {7749,[110,775]},
1168     {7767,[112,775]},
1169     {7769,[114,775]},
1170     {7777,[115,775]},
1171     {7787,[116,775]},
1172     {7815,[119,775]},
1173     {7819,[120,775]},
1174     {7823,[121,775]},
1175     {380,[122,775]},
1176     {7835,[383,775]},
1177     {7780,[83,769,775]},
1178     {7781,[115,769,775]},
1179     {784,[774,775]},
1180     {7782,[83,780,775]},
1181     {7783,[115,780,775]},
1182     {7784,[83,803,775]},
1183     {7785,[115,803,775]},
1184     {196,[65,776]},
1185     {203,[69,776]},
1186     {7718,[72,776]},
1187     {207,[73,776]},
1188     {214,[79,776]},
1189     {220,[85,776]},
1190     {7812,[87,776]},
1191     {7820,[88,776]},
1192     {376,[89,776]},
1193     {228,[97,776]},
1194     {235,[101,776]},
1195     {7719,[104,776]},
1196     {239,[105,776]},
1197     {246,[111,776]},
1198     {7831,[116,776]},
1199     {252,[117,776]},
1200     {7813,[119,776]},
1201     {7821,[120,776]},
1202     {255,[121,776]},
1203     {1242,[399,776]},
1204     {1258,[415,776]},
1205     {1243,[601,776]},
1206     {1259,[629,776]},
1207     {7758,[79,771,776]},
1208     {7759,[111,771,776]},
1209     {7802,[85,772,776]},
1210     {7803,[117,772,776]},
1211     {938,[921,776]},
1212     {939,[933,776]},
1213     {970,[953,776]},
1214     {971,[965,776]},
1215     {980,[978,776]},
1216     {1031,[1030,776]},
1217     {1234,[1040,776]},
1218     {1025,[1045,776]},
1219     {1244,[1046,776]},
1220     {1246,[1047,776]},
1221     {1252,[1048,776]},
1222     {1254,[1054,776]},
1223     {1264,[1059,776]},
1224     {1268,[1063,776]},
1225     {1272,[1067,776]},
1226     {1235,[1072,776]},
1227     {1105,[1077,776]},
1228     {1245,[1078,776]},
1229     {1247,[1079,776]},
1230     {1253,[1080,776]},
1231     {1255,[1086,776]},
1232     {1265,[1091,776]},
1233     {1269,[1095,776]},
1234     {1273,[1099,776]},
1235     {1111,[1110,776]},
1236     {7842,[65,777]},
1237     {7866,[69,777]},
1238     {7880,[73,777]},
1239     {7886,[79,777]},
1240     {7910,[85,777]},
1241     {7926,[89,777]},
1242     {7843,[97,777]},
1243     {7867,[101,777]},
1244     {7881,[105,777]},
1245     {7887,[111,777]},
1246     {7911,[117,777]},
1247     {7927,[121,777]},
1248     {7848,[65,770,777]},
1249     {7874,[69,770,777]},
1250     {7892,[79,770,777]},
1251     {7849,[97,770,777]},
1252     {7875,[101,770,777]},
1253     {7893,[111,770,777]},
1254     {7858,[65,774,777]},
1255     {7859,[97,774,777]},
1256     {7902,[79,795,777]},
1257     {7916,[85,795,777]},
1258     {7903,[111,795,777]},
1259     {7917,[117,795,777]},
1260     {197,[65,778]},
1261     {366,[85,778]},
1262     {229,[97,778]},
1263     {367,[117,778]},
1264     {7832,[119,778]},
1265     {7833,[121,778]},
1266     {336,[79,779]},
1267     {368,[85,779]},
1268     {337,[111,779]},
1269     {369,[117,779]},
1270     {1266,[1059,779]},
1271     {1267,[1091,779]},
1272     {461,[65,780]},
1273     {268,[67,780]},
1274     {270,[68,780]},
1275     {282,[69,780]},
1276     {486,[71,780]},
1277     {463,[73,780]},
1278     {488,[75,780]},
1279     {317,[76,780]},
1280     {327,[78,780]},
1281     {465,[79,780]},
1282     {344,[82,780]},
1283     {352,[83,780]},
1284     {356,[84,780]},
1285     {467,[85,780]},
1286     {381,[90,780]},
1287     {462,[97,780]},
1288     {269,[99,780]},
1289     {271,[100,780]},
1290     {283,[101,780]},
1291     {487,[103,780]},
1292     {464,[105,780]},
1293     {496,[106,780]},
1294     {489,[107,780]},
1295     {318,[108,780]},
1296     {328,[110,780]},
1297     {466,[111,780]},
1298     {345,[114,780]},
1299     {353,[115,780]},
1300     {357,[116,780]},
1301     {468,[117,780]},
1302     {382,[122,780]},
1303     {494,[439,780]},
1304     {495,[658,780]},
1305     {473,[85,776,780]},
1306     {474,[117,776,780]},
1307     {901,[168,781]},
1308     {912,[953,776,781]},
1309     {944,[965,776,781]},
1310     {902,[913,781]},
1311     {904,[917,781]},
1312     {905,[919,781]},
1313     {906,[921,781]},
1314     {908,[927,781]},
1315     {910,[933,781]},
1316     {911,[937,781]},
1317     {940,[945,781]},
1318     {941,[949,781]},
1319     {942,[951,781]},
1320     {943,[953,781]},
1321     {972,[959,781]},
1322     {973,[965,781]},
1323     {974,[969,781]},
1324     {979,[978,781]},
1325     {512,[65,783]},
1326     {516,[69,783]},
1327     {520,[73,783]},
1328     {524,[79,783]},
1329     {528,[82,783]},
1330     {532,[85,783]},
1331     {513,[97,783]},
1332     {517,[101,783]},
1333     {521,[105,783]},
1334     {525,[111,783]},
1335     {529,[114,783]},
1336     {533,[117,783]},
1337     {1142,[1140,783]},
1338     {1143,[1141,783]},
1339     {514,[65,785]},
1340     {518,[69,785]},
1341     {522,[73,785]},
1342     {526,[79,785]},
1343     {530,[82,785]},
1344     {534,[85,785]},
1345     {515,[97,785]},
1346     {519,[101,785]},
1347     {523,[105,785]},
1348     {527,[111,785]},
1349     {531,[114,785]},
1350     {535,[117,785]},
1351     {8072,[913,837,787]},
1352     {8088,[919,837,787]},
1353     {8104,[937,837,787]},
1354     {8064,[945,837,787]},
1355     {8080,[951,837,787]},
1356     {8096,[969,837,787]},
1357     {7944,[913,787]},
1358     {7960,[917,787]},
1359     {7976,[919,787]},
1360     {7992,[921,787]},
1361     {8008,[927,787]},
1362     {8040,[937,787]},
1363     {7936,[945,787]},
1364     {7952,[949,787]},
1365     {7968,[951,787]},
1366     {7984,[953,787]},
1367     {8000,[959,787]},
1368     {8164,[961,787]},
1369     {8016,[965,787]},
1370     {8032,[969,787]},
1371     {8073,[913,837,788]},
1372     {8089,[919,837,788]},
1373     {8105,[937,837,788]},
1374     {8065,[945,837,788]},
1375     {8081,[951,837,788]},
1376     {8097,[969,837,788]},
1377     {7945,[913,788]},
1378     {7961,[917,788]},
1379     {7977,[919,788]},
1380     {7993,[921,788]},
1381     {8009,[927,788]},
1382     {8172,[929,788]},
1383     {8025,[933,788]},
1384     {8041,[937,788]},
1385     {7937,[945,788]},
1386     {7953,[949,788]},
1387     {7969,[951,788]},
1388     {7985,[953,788]},
1389     {8001,[959,788]},
1390     {8165,[961,788]},
1391     {8017,[965,788]},
1392     {8033,[969,788]},
1393     {416,[79,795]},
1394     {431,[85,795]},
1395     {417,[111,795]},
1396     {432,[117,795]},
1397     {7840,[65,803]},
1398     {7684,[66,803]},
1399     {7692,[68,803]},
1400     {7864,[69,803]},
1401     {7716,[72,803]},
1402     {7882,[73,803]},
1403     {7730,[75,803]},
1404     {7734,[76,803]},
1405     {7746,[77,803]},
1406     {7750,[78,803]},
1407     {7884,[79,803]},
1408     {7770,[82,803]},
1409     {7778,[83,803]},
1410     {7788,[84,803]},
1411     {7908,[85,803]},
1412     {7806,[86,803]},
1413     {7816,[87,803]},
1414     {7924,[89,803]},
1415     {7826,[90,803]},
1416     {7841,[97,803]},
1417     {7685,[98,803]},
1418     {7693,[100,803]},
1419     {7865,[101,803]},
1420     {7717,[104,803]},
1421     {7883,[105,803]},
1422     {7731,[107,803]},
1423     {7735,[108,803]},
1424     {7747,[109,803]},
1425     {7751,[110,803]},
1426     {7885,[111,803]},
1427     {7771,[114,803]},
1428     {7779,[115,803]},
1429     {7789,[116,803]},
1430     {7909,[117,803]},
1431     {7807,[118,803]},
1432     {7817,[119,803]},
1433     {7925,[121,803]},
1434     {7827,[122,803]},
1435     {7906,[79,795,803]},
1436     {7920,[85,795,803]},
1437     {7907,[111,795,803]},
1438     {7921,[117,795,803]},
1439     {7794,[85,804]},
1440     {7795,[117,804]},
1441     {7680,[65,805]},
1442     {7681,[97,805]},
1443     {199,[67,807]},
1444     {7696,[68,807]},
1445     {290,[71,807]},
1446     {7720,[72,807]},
1447     {310,[75,807]},
1448     {315,[76,807]},
1449     {325,[78,807]},
1450     {342,[82,807]},
1451     {350,[83,807]},
1452     {354,[84,807]},
1453     {231,[99,807]},
1454     {7697,[100,807]},
1455     {291,[103,807]},
1456     {7721,[104,807]},
1457     {311,[107,807]},
1458     {316,[108,807]},
1459     {326,[110,807]},
1460     {343,[114,807]},
1461     {351,[115,807]},
1462     {355,[116,807]},
1463     {260,[65,808]},
1464     {280,[69,808]},
1465     {302,[73,808]},
1466     {490,[79,808]},
1467     {370,[85,808]},
1468     {261,[97,808]},
1469     {281,[101,808]},
1470     {303,[105,808]},
1471     {491,[111,808]},
1472     {371,[117,808]},
1473     {7698,[68,813]},
1474     {7704,[69,813]},
1475     {7740,[76,813]},
1476     {7754,[78,813]},
1477     {7792,[84,813]},
1478     {7798,[85,813]},
1479     {7699,[100,813]},
1480     {7705,[101,813]},
1481     {7741,[108,813]},
1482     {7755,[110,813]},
1483     {7793,[116,813]},
1484     {7799,[117,813]},
1485     {7722,[72,814]},
1486     {7723,[104,814]},
1487     {7706,[69,816]},
1488     {7724,[73,816]},
1489     {7796,[85,816]},
1490     {7707,[101,816]},
1491     {7725,[105,816]},
1492     {7797,[117,816]},
1493     {7686,[66,817]},
1494     {7694,[68,817]},
1495     {7732,[75,817]},
1496     {7738,[76,817]},
1497     {7752,[78,817]},
1498     {7774,[82,817]},
1499     {7790,[84,817]},
1500     {7828,[90,817]},
1501     {7687,[98,817]},
1502     {7695,[100,817]},
1503     {7830,[104,817]},
1504     {7733,[107,817]},
1505     {7739,[108,817]},
1506     {7753,[110,817]},
1507     {7775,[114,817]},
1508     {7791,[116,817]},
1509     {7829,[122,817]},
1510     {8129,[168,834]},
1511     {8151,[953,776,834]},
1512     {8167,[965,776,834]},
1513     {8078,[913,837,787,834]},
1514     {8094,[919,837,787,834]},
1515     {8110,[937,837,787,834]},
1516     {8070,[945,837,787,834]},
1517     {8086,[951,837,787,834]},
1518     {8102,[969,837,787,834]},
1519     {7950,[913,787,834]},
1520     {7982,[919,787,834]},
1521     {7998,[921,787,834]},
1522     {8046,[937,787,834]},
1523     {7942,[945,787,834]},
1524     {7974,[951,787,834]},
1525     {7990,[953,787,834]},
1526     {8022,[965,787,834]},
1527     {8038,[969,787,834]},
1528     {8079,[913,837,788,834]},
1529     {8095,[919,837,788,834]},
1530     {8111,[937,837,788,834]},
1531     {8071,[945,837,788,834]},
1532     {8087,[951,837,788,834]},
1533     {8103,[969,837,788,834]},
1534     {7951,[913,788,834]},
1535     {7983,[919,788,834]},
1536     {7999,[921,788,834]},
1537     {8031,[933,788,834]},
1538     {8047,[937,788,834]},
1539     {7943,[945,788,834]},
1540     {7975,[951,788,834]},
1541     {7991,[953,788,834]},
1542     {8023,[965,788,834]},
1543     {8039,[969,788,834]},
1544     {8119,[945,837,834]},
1545     {8135,[951,837,834]},
1546     {8183,[969,837,834]},
1547     {8118,[945,834]},
1548     {8134,[951,834]},
1549     {8150,[953,834]},
1550     {8166,[965,834]},
1551     {8182,[969,834]},
1552     {8143,[8127,834]},
1553     {8159,[8190,834]},
1554     {8124,[913,837]},
1555     {8140,[919,837]},
1556     {8188,[937,837]},
1557     {8115,[945,837]},
1558     {8131,[951,837]},
1559     {8179,[969,837]},
1560     {64302,[1488,1463]},
1561     {64287,[1522,1463]},
1562     {64303,[1488,1464]},
1563     {64331,[1493,1465]},
1564     {64304,[1488,1468]},
1565     {64305,[1489,1468]},
1566     {64306,[1490,1468]},
1567     {64307,[1491,1468]},
1568     {64308,[1492,1468]},
1569     {64309,[1493,1468]},
1570     {64310,[1494,1468]},
1571     {64312,[1496,1468]},
1572     {64313,[1497,1468]},
1573     {64314,[1498,1468]},
1574     {64315,[1499,1468]},
1575     {64316,[1500,1468]},
1576     {64318,[1502,1468]},
1577     {64320,[1504,1468]},
1578     {64321,[1505,1468]},
1579     {64323,[1507,1468]},
1580     {64324,[1508,1468]},
1581     {64326,[1510,1468]},
1582     {64327,[1511,1468]},
1583     {64328,[1512,1468]},
1584     {64329,[1513,1468]},
1585     {64330,[1514,1468]},
1586     {64332,[1489,1471]},
1587     {64333,[1499,1471]},
1588     {64334,[1508,1471]},
1589     {64300,[1513,1468,1473]},
1590     {64298,[1513,1473]},
1591     {64301,[1513,1468,1474]},
1592     {64299,[1513,1474]},
1593     {2392,[2325,2364]},
1594     {2393,[2326,2364]},
1595     {2394,[2327,2364]},
1596     {2395,[2332,2364]},
1597     {2396,[2337,2364]},
1598     {2397,[2338,2364]},
1599     {2345,[2344,2364]},
1600     {2398,[2347,2364]},
1601     {2399,[2351,2364]},
1602     {2353,[2352,2364]},
1603     {2356,[2355,2364]},
1604     {2524,[2465,2492]},
1605     {2525,[2466,2492]},
1606     {2480,[2476,2492]},
1607     {2527,[2479,2492]},
1608     {2507,[2503,2494]},
1609     {2508,[2503,2519]},
1610     {2649,[2582,2620]},
1611     {2650,[2583,2620]},
1612     {2651,[2588,2620]},
1613     {2652,[2593,2620]},
1614     {2654,[2603,2620]},
1615     {2908,[2849,2876]},
1616     {2909,[2850,2876]},
1617     {2911,[2863,2876]},
1618     {2891,[2887,2878]},
1619     {2888,[2887,2902]},
1620     {2892,[2887,2903]},
1621     {3018,[3014,3006]},
1622     {3019,[3015,3006]},
1623     {2964,[2962,3031]},
1624     {3020,[3014,3031]},
1625     {3144,[3142,3158]},
1626     {3274,[3270,3266]},
1627     {3264,[3263,3285]},
1628     {3275,[3270,3266,3285]},
1629     {3271,[3270,3285]},
1630     {3272,[3270,3286]},
1631     {3402,[3398,3390]},
1632     {3403,[3399,3390]},
1633     {3404,[3398,3415]},
1634     {3635,[3661,3634]},
1635     {3763,[3789,3762]},
1636     {3955,[3954,3953]},
1637     {3957,[3956,3953]},
1638     {3959,[4018,3968,3953]},
1639     {3961,[4019,3968,3953]},
1640     {3958,[4018,3968]},
1641     {3960,[4019,3968]},
1642     {3945,[3904,4021]},
1643     {4025,[3984,4021]},
1644     {3907,[3906,4023]},
1645     {3917,[3916,4023]},
1646     {3922,[3921,4023]},
1647     {3927,[3926,4023]},
1648     {3932,[3931,4023]},
1649     {3987,[3986,4023]},
1650     {3997,[3996,4023]},
1651     {4002,[4001,4023]},
1652     {4007,[4006,4023]},
1653     {4012,[4011,4023]},
1654     {12436,[12358,12441]},
1655     {12364,[12363,12441]},
1656     {12366,[12365,12441]},
1657     {12368,[12367,12441]},
1658     {12370,[12369,12441]},
1659     {12372,[12371,12441]},
1660     {12374,[12373,12441]},
1661     {12376,[12375,12441]},
1662     {12378,[12377,12441]},
1663     {12380,[12379,12441]},
1664     {12382,[12381,12441]},
1665     {12384,[12383,12441]},
1666     {12386,[12385,12441]},
1667     {12389,[12388,12441]},
1668     {12391,[12390,12441]},
1669     {12393,[12392,12441]},
1670     {12400,[12399,12441]},
1671     {12403,[12402,12441]},
1672     {12406,[12405,12441]},
1673     {12409,[12408,12441]},
1674     {12412,[12411,12441]},
1675     {12446,[12445,12441]},
1676     {12532,[12454,12441]},
1677     {12460,[12459,12441]},
1678     {12462,[12461,12441]},
1679     {12464,[12463,12441]},
1680     {12466,[12465,12441]},
1681     {12468,[12467,12441]},
1682     {12470,[12469,12441]},
1683     {12472,[12471,12441]},
1684     {12474,[12473,12441]},
1685     {12476,[12475,12441]},
1686     {12478,[12477,12441]},
1687     {12480,[12479,12441]},
1688     {12482,[12481,12441]},
1689     {12485,[12484,12441]},
1690     {12487,[12486,12441]},
1691     {12489,[12488,12441]},
1692     {12496,[12495,12441]},
1693     {12499,[12498,12441]},
1694     {12502,[12501,12441]},
1695     {12505,[12504,12441]},
1696     {12508,[12507,12441]},
1697     {12535,[12527,12441]},
1698     {12536,[12528,12441]},
1699     {12537,[12529,12441]},
1700     {12538,[12530,12441]},
1701     {12542,[12541,12441]},
1702     {12401,[12399,12442]},
1703     {12404,[12402,12442]},
1704     {12407,[12405,12442]},
1705     {12410,[12408,12442]},
1706     {12413,[12411,12442]},
1707     {12497,[12495,12442]},
1708     {12500,[12498,12442]},
1709     {12503,[12501,12442]},
1710     {12506,[12504,12442]},
1711     {12509,[12507,12442]}}.
1712