diff --git a/zx b/zx index 16c101a..d7215b0 100755 --- a/zx +++ b/zx @@ -550,16 +550,41 @@ update_version(Realm, Name, OldVersion, NewVersion, OldMeta) -> when Path :: file:filename(). add_realm(Path) -> - case filelib:is_regular(Path) of - true -> - ok = log(info, "I would install this now, were I implemented."), - halt(0); - false -> - ok = log(warning, "Realm file not found at ~ts.", [Path]), + case file:read_file(Path) of + {ok, Data} -> + Digest = crypto:hash(sha512, Data), + Text = integer_to_list(binary:decode_unsigned(Digest, big), 16), + ok = log(info, "SHA512 of ~ts: ~ts", [Path, Text]), + add_realm(Path, Data); + {error, enoent} -> + ok = log(warning, "FAILED: ~ts does not exist.", [Path]), + halt(1); + {error, eisdir} -> + ok = log(warning, "FAILED: ~ts is a directory, not a realm file.", [Path]), halt(1) end. +-spec add_realm(Path, Data) -> no_return() + when Path :: file:filename(), + Data :: binary(). + +add_realm(Path, Data) -> + case erl_tar:extract({binary, Data}, [compressed, {cwd, zomp_dir()}]) of + ok -> + {Realm, _} = string:take(filename:basename(Path), ".", true), + ok = log(info, "Realm ~ts is now visible to this system.", [Realm]), + halt(0); + {error, invalid_tar_checksum} -> + ok = log(warning, "FAILED: ~ts is not a valid realm file.", [Path]), + halt(1); + {error, eof} -> + ok = log(warning, "FAILED: ~ts is not a valid realm file.", [Path]), + halt(1) + end. + + + %%% Drop dependency -spec drop_dep(package_id()) -> no_return(). @@ -612,8 +637,46 @@ drop_key({Realm, KeyName}) -> -spec drop_realm(realm()) -> no_return(). drop_realm(Realm) -> - ok = log(info, "I would totally drop ~ts right now if I could.", [Realm]), - halt(0). + ok = file:set_cwd(zomp_dir()), + RealmConf = realm_conf(Realm), + case filelib:is_regular(RealmConf) of + true -> + Message = + "~n" + " WARNING: Are you SURE you want to remove realm ~ts?~n" + " (Only \"Y\" will confirm this action.)~n", + ok = io:format(Message, [Realm]), + case get_input() of + "Y" -> + ok = file:delete(RealmConf), + clear_keys(Realm); + _ -> + ok = log(info, "Aborting."), + halt(0) + end; + false -> + ok = log(warning, "Realm conf ~ts not found.", [RealmConf]), + clear_keys(Realm) + end. + + +-spec clear_keys(realm()) -> no_return(). + +clear_keys(Realm) -> + KeyDir = filename:join([zomp_dir(), "key", Realm]), + case filelib:is_dir(KeyDir) of + true -> + ok = log(info, "Wiping key dir ~ts", [KeyDir]), + Keys = filelib:wildcard(KeyDir ++ "/**"), + Delete = fun(K) -> file:delete(K) end, + ok = lists:foreach(Delete, Keys), + ok = file:del_dir(KeyDir), + ok = log(info, "Done!"), + halt(0); + false -> + ok = log(warning, "Keydir ~ts not found", [KeyDir]), + halt(1) + end. @@ -1789,34 +1852,36 @@ create_realm(ZompConf, Realm, ExAddress, ExPort, InPort, UserName, Email) -> -spec create_realmfile(realm()) -> no_return(). create_realmfile(Realm) -> - ConfPath = filename:join(zomp_dir(), realm_file(Realm)), + ConfPath = filename:join(zomp_dir(), realm_conf(Realm)), case file:consult(ConfPath) of {ok, RealmConf} -> ok = log(info, "Realm found, creating realm file..."), + {revision, Revision} = lists:keyfind(revision, 1, RealmConf), {realm_keys, RealmKeys} = lists:keyfind(realm_keys, 1, RealmConf), {package_keys, PackageKeys} = lists:keyfind(package_keys, 1, RealmConf), RealmKeyIDs = [element(1, K) || K <- RealmKeys], PackageKeyIDs = [element(1, K) || K <- PackageKeys], - create_realmfile(Realm, ConfPath, RealmKeyIDs, PackageKeyIDs); + create_realmfile(Realm, ConfPath, Revision, RealmKeyIDs, PackageKeyIDs); {error, enoent} -> ok = log(warning, "There is no configured realm called ~ts.", [Realm]), halt(1) end. --spec create_realmfile(Realm, ConfPath, RealmKeyIDs, PackageKeyIDs) -> ok +-spec create_realmfile(Realm, ConfPath, Revision, RealmKeyIDs, PackageKeyIDs) -> ok when Realm :: realm(), ConfPath :: file:filename(), + Revision :: non_neg_integer(), RealmKeyIDs :: [key_id()], PackageKeyIDs :: [key_id()]. -create_realmfile(Realm, ConfPath, RealmKeyIDs, PackageKeyIDs) -> +create_realmfile(Realm, ConfPath, Revision, RealmKeyIDs, PackageKeyIDs) -> {ok, CWD} = file:get_cwd(), ok = file:set_cwd(zomp_dir()), KeyPath = fun({R, K}) -> filename:join(["key", R, K ++ ".pub.der"]) end, RealmKeyPaths = lists:map(KeyPath, RealmKeyIDs), PackageKeyPaths = lists:map(KeyPath, PackageKeyIDs), Targets = [filename:basename(ConfPath) | RealmKeyPaths ++ PackageKeyPaths], - OutFile = filename:join(CWD, Realm ++ ".zrf"), + OutFile = filename:join(CWD, Realm ++ "." ++ integer_to_list(Revision) ++ ".zrf"), ok = erl_tar:create(OutFile, Targets, [compressed]), ok = log(info, "Realm conf file written to ~ts", [OutFile]), halt(0). @@ -2355,22 +2420,30 @@ hurr() -> io:format("That isn't an option.~n"). ensure_zomp_home() -> ZompDir = zomp_dir(), case filelib:is_dir(ZompDir) of - true -> - ok; - false -> - {ok, CWD} = file:get_cwd(), - force_dir(ZompDir), - ok = file:set_cwd(ZompDir), - SubDirs = ["tmp", "key", "var", "lib", "zrp", "etc"], - ok = lists:foreach(fun file:make_dir/1, SubDirs), - ok = write_terms(default_realm_file(), default_realm()), - ok = write_terms("zomp.conf", default_conf()), - ok = file:write_file(default_pubkey_file(), default_pubkey()), - ok = log(info, "Zomp userland directory initialized."), - file:set_cwd(CWD) + true -> ok; + false -> setup(ZompDir) end. +-spec setup(ZompDir :: file:filename()) -> ok. + +setup(ZompDir) -> + {ok, CWD} = file:get_cwd(), + ok = force_dir(ZompDir), + ok = file:set_cwd(ZompDir), + SubDirs = ["tmp", "key", "var", "lib", "zrp", "etc"], + ok = lists:foreach(fun file:make_dir/1, SubDirs), + ok = setup_otpr(), + ok = log(info, "Zomp userland directory initialized."), + file:set_cwd(CWD). + + +-spec setup_otpr() -> ok. + +setup_otpr() -> + log(info, "Here should pull otpr.0.zrf and install it..."). + + -spec zomp_dir() -> file:filename(). %% @private %% Check the host OS and return the absolute path to the zomp filesystem root. @@ -2445,87 +2518,16 @@ force_dir(Path) -> end. - -%%% Persistent Zomp State -%%% -%%% The following functions maintain constants or very light convenience functions -%%% that make use of system-wide constants such as the default realm name, default -%%% public key, and other data necessary to bootstrap the system. - - --spec default_realm_file() -> RealmFileName - when RealmFileName :: file:filename(). -%% @private -%% Return the base filename of the default realm file. - -default_realm_file() -> - realm_file(default_realm_name()). - - --spec default_realm_name() -> Name - when Name :: string(). -%% @private -%% Return the name of the default realm. - -default_realm_name() -> - "otpr". - - --spec realm_file(Realm) -> RealmFileName +-spec realm_conf(Realm) -> RealmFileName when Realm :: string(), RealmFileName :: file:filename(). %% @private %% Take a realm name, and return the name of the realm filename that would result. -realm_file(Realm) -> +realm_conf(Realm) -> Realm ++ ".realm". --spec default_realm() -> [{Key :: atom(), Value :: term()}]. -%% @private -%% Returns the default realm file's data contents for the default "otpr" realm. - -default_realm() -> - [{realm, "otpr"}, - {revision, 0}, - {prime, {"repo.psychobitch.party", 11311}}, - {private, [{"localhost", 11311}]}, - {mirrors, []}, - {sysops, [{"otpr, ""zxq9"}]}, - {realm_keys, []}, - {package_keys, [default_pubkey_file()]}]. - - --spec default_conf() -> [{Key :: atom(), Value :: term()}]. -%% @private -%% Return the default local config values for a zomp server. -%% The external and local port values are global values needed to make a zomp server -%% work in the face of unique port forwarding and NAT configurations outside the control -%% of the zomp server itself. zx references these values in a few places (namely when -%% setting up a mirror or prime realm). -default_conf() -> - [{external_port, 11311}, - {local_port, 11311}]. - - --spec default_pubkey_file() -> file:filename(). -%% @private -%% Returns the default filename of the default public key. - -default_pubkey_file() -> - "key/otpr.1.pub.der". - - --spec default_pubkey() -> binary(). -%% @private -%% This function stores the binary contents of the default public key in DER format. -%% Doing this in a function is essentially like using a herefile in Bash. - -default_pubkey() -> - <<1170526623609313331798826318972097080557896621948083159586373016346811570540623523814426011993490293167510658875163780852129579343891111576406428675491227868125570029553836721253582239727832008666977889522526670373902361492830918639140761847180559556687253204307494936306069307171528877400209962142787058308740221939755312361860413975531508150223291108422638532792576263104963638096818852870688582998502102536693308795214193253585166432265144396969870581676155216529809785753049835842318198805379857414606363727445230640910295705259948273015496668069952400995675937310182784823621435512613227257682702758407858036197683634666558131083559654726498186745235163628111760825026969986395769481087197994986427088838210048234736434112178729013032345213637282290815839027637504309538687095441687636356524193476275012030156571775013858217400602512194340193440681965829477411264954556799403863486012736713903706193506878410947578154040532592626008808497608835124296529017804159705286317715644155305350224257244260965453649874471033452253082499940845996170964558413968751507443986189697350023010630553524737002017543233621194508406455743465763341654345366274867913624544034721065244860576536017333528275040881674913063184272153529110886460286503455305330851192409414251325951739930514383412398798397169143552351929225078321776410580550088942920371869276662363003778677125037156672547734001647521245835866935294771855501141038223226549689862909953059166203977747766244019902323008152684587630882351278639697258019126733864910210128726118293540255959256597047563483255422642476502931615170150279457262340283463240052013184396583425577647694479205638188304711342708918448926127873312263215725459445847837288305565332375343953499300740443134048756072889091269830410360478466021318806219775513929766205963920179119585525683940978348051934951531003108279739296413836014878110298764281501544267131870022937730804080147990914120458451989661878314958524775077357936603530507381414681306510832486998678859256113064859502255575935373463709491675650991615474781558091560988205268798622776917923800097513069754689850980381850490662482961403587126912566501355644996590916922352735199214989138312856189875740424585814665007172318472691695957369820456341466786796592662135451831988129143024570641715114511174217352536557906484463741194647291182294337994718316817204867347695280457082728945911284833182013377663664430399865622471148347081767689841618546822415385957879982189694968028649835009229433349600455509536803831313830531746047425571328569634168722980491088303167148354034563578494773467308480373559768673286318322053544821433023042519594934353482721862948302631174310147010936830502360070216922584309962755494775082047690911998699570511078636376582952731884810583686700059291779239354983531555181641890341326596564548265142534064300496297926337825631921898202540803202984034394784105085299461195927463845508809485122164029528839799785844442443320039670416946533059409608926282019699119974258605650707621139750878861541251137000244133051922824004103328765954846809123299108643057388278106591988288588948726535195014652816533709432709443954841948958140326831643843906635067011302827793775757370405519240285135798743643797930642236731316466261629711900502696653563418054590076289653489719291121150266002099855392711464520928906433276097459061937053797457493166175864841786220404163949123451204756345296224150348843428777300804284267552332261715309580834396983346300530128191498649494481252342446265281499938013011901846865327797551832040198638001834019915656624142453248674154025598865589700532971711073725385563400552303085348956272116643141577079495146481883784661063082399836741351657205056526803513667042134368197760702297797779121467458147679998609606364108573808591354056588770173469993932525100580531597375569598234130308636537517111449993369547954653263045866310538500083896993112212303722148462970005994202673301481606806414256044693412925931019110552827804892050433228331280670562421203245853375417503339200768693046544396231856765919093252078432727627221414636522639011044239359484661269388619025699989119275623338551483041590123908337000853294371085777425084159087803966041644743349623092361390058115563570787103198976595362533473421958104661160820266906203090829648646902638295050336316799572281472144754384682003756790117478811155220025535420078485563985223415989335480370251115982845339833011445261624828025843177973576483738938303080242315615333593789609241843889852679993907685041671938947639167721054076202421174520920916996533102606039402530751673420224664619445635819542316713250359524898015718931583729548373297621243023115983588963506710418076848806241677618452223292483533560902680339825696167663170302616711331313490757011906928728140010004845723770802553281761773606296962670294026670439797097955228790673139658966545527614535446680187443733681726438681960897106751213102099950826404109307953852794370653372653043187474529370340385390651752792530497659674388660225:16496>>. - - - %%% Usage