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