Installer.Mod 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. MODULE Installer; (** AUTHOR "staubesv"; PURPOSE "Installer"; *)
  2. IMPORT
  3. KernelLog, Streams, Commands, Strings, Disks, Files, AosUnzip := Unzip, Partitions, PartitionsLib, Codecs,
  4. XML, XMLScanner, XMLParser, XMLObjects;
  5. CONST
  6. AosPartitionType = 76;
  7. Free = -1;
  8. AosFsName = "AosFS";
  9. DefaultMBRFile = "OBEMBR.BIN";
  10. DefaultBootLoader = "OBL.Bin";
  11. DefaultBootfile = "IDE.Bin";
  12. DefaultUsbBootfile = "USB.Bin";
  13. DefaultBootManMBR = "BootManagerMBR.Bin";
  14. DefaultBootManRest = "BootManagerTail.Bin";
  15. BootVolString = "AOS AosFS "; (* dev#part will be appended *)
  16. DefaultPrefix = "INSTALLER";
  17. MaxPackages = 128;
  18. XmlPackage = "Package";
  19. XmlPackageNumber = "nr";
  20. XmlPackageFilename = "file";
  21. XmlPackageName = "name";
  22. XmlPackageDescription = "description";
  23. XmlPackageInstall="install";
  24. XmlInstallYes="YES";
  25. XmlInstallNo="NO";
  26. XmlInstallRequired="REQUIRED";
  27. Invalid = -1;
  28. Mandatory* = 0;
  29. OptionalYes* = 1;
  30. OptionalNo* = 2;
  31. NotAllowed* = 3;
  32. (* AosFS block size [Bytes] *)
  33. BlockSize = 4096;
  34. (* Overhead in file system metadata per file (guess) *)
  35. FsMetaOverheadPerFile = 128;
  36. NofSteps* = 12;
  37. Undefined* = 0;
  38. WriteMBR* = 1;
  39. CreatePartition* = 2;
  40. ChangeType* = 3;
  41. Activate* = 4;
  42. Format* = 5;
  43. UpdateBootfile* = 6;
  44. SetConfig* = 7;
  45. InstallBootManager* = 8;
  46. Mount* = 9;
  47. InstallPackages* = 10;
  48. Unmount* = 11;
  49. TYPE
  50. Configuration* = OBJECT
  51. VAR
  52. steps : ARRAY NofSteps OF LONGINT;
  53. (* WriteMBR: MBR filename *)
  54. mbrFile* : Files.FileName;
  55. (* CreatePartition: partition size *)
  56. size* : LONGINT;
  57. (* Format: Boot loader and Boot file filenames *)
  58. bootloader* : Files.FileName;
  59. bootfile* : Files.FileName; (* also for updateBootfile *)
  60. (* SetConfig: *)
  61. configTable- : PartitionsLib.ConfigTable;
  62. (* Install BB boot manager into MBR? *)
  63. bootManMBR*, bootManRest* : Files.FileName;
  64. (* Mount: File system prefix to be used *)
  65. mountPrefix* : Files.Prefix;
  66. (* InstallPackages: Package description *)
  67. packages : Packages;
  68. disk : PartitionsLib.Disk;
  69. partition : LONGINT;
  70. diskpartString : PartitionsLib.String;
  71. PROCEDURE SetInstallStep*(step : LONGINT; doStep : BOOLEAN; VAR msg : ARRAY OF CHAR) : BOOLEAN;
  72. BEGIN
  73. IF ~IsValidStepNumber(step) THEN msg := "Invalid installation step specified"; RETURN FALSE; END;
  74. CASE steps[step] OF
  75. |Mandatory:
  76. IF ~doStep THEN msg := "This installation step is mandatory"; RETURN FALSE; END;
  77. |OptionalYes:
  78. IF ~doStep THEN steps[step] := OptionalNo; END;
  79. |OptionalNo:
  80. IF doStep THEN steps[step] := OptionalYes; END;
  81. |NotAllowed:
  82. IF doStep THEN msg := "This installation step is not allowed"; RETURN FALSE; END;
  83. ELSE
  84. HALT(99);
  85. END;
  86. RETURN TRUE;
  87. END SetInstallStep;
  88. PROCEDURE IsValidStepNumber(stepNr : LONGINT) : BOOLEAN;
  89. BEGIN
  90. RETURN (0 <= stepNr) & (stepNr < NofSteps);
  91. END IsValidStepNumber;
  92. (* Return TRUE of the specified install step will be performed, FALSE otherwise *)
  93. PROCEDURE DoStep*(step : LONGINT) : BOOLEAN;
  94. BEGIN
  95. ASSERT(IsValidStepNumber(step));
  96. RETURN (steps[step] = Mandatory) OR (steps[step] = OptionalYes);
  97. END DoStep;
  98. (* Return the number of steps that will be performed *)
  99. PROCEDURE GetNofSteps() : LONGINT;
  100. VAR nofSteps, i : LONGINT;
  101. BEGIN
  102. nofSteps := 0;
  103. FOR i := 0 TO LEN(steps)-1 DO
  104. IF DoStep(i) THEN INC(nofSteps); END;
  105. END;
  106. RETURN nofSteps;
  107. END GetNofSteps;
  108. PROCEDURE IsUsbDisk() : BOOLEAN;
  109. BEGIN
  110. RETURN ((LEN(diskpartString) > 2) & (diskpartString[0] = "U") & (diskpartString[1] = "S") & (diskpartString[2] = "B")) OR
  111. (* WinAOS hack: Assume that removable devices are USB devices *)
  112. (Strings.Match("PhysicalDrive*", diskpartString) & (disk.device # NIL) & (Disks.Removable IN disk.device.flags));
  113. END IsUsbDisk;
  114. PROCEDURE SpaceAvailable*() : LONGINT;
  115. VAR spaceAvailable : LONGINT;
  116. BEGIN
  117. spaceAvailable := (disk.table[partition].size DIV 1024) * disk.device.blockSize;
  118. spaceAvailable := spaceAvailable - 640; (* 640KB for boot file *)
  119. RETURN spaceAvailable;
  120. END SpaceAvailable;
  121. PROCEDURE CheckConfiguration*(w : Streams.Writer) : BOOLEAN;
  122. VAR errors : LONGINT; installSize, installSizeOnDisk, nofEntries : LONGINT;
  123. PROCEDURE ShowError(CONST string : ARRAY OF CHAR);
  124. BEGIN
  125. INC(errors);
  126. w.String("Error "); w.Int(errors, 2); w.String(": "); w.String(string);
  127. END ShowError;
  128. PROCEDURE CheckFile(CONST filename, description : ARRAY OF CHAR);
  129. BEGIN
  130. IF ~FileExists(filename) THEN
  131. ShowError(description); w.String(" "); w.String(filename); w.String(" not found"); w.Ln;
  132. END;
  133. END CheckFile;
  134. BEGIN
  135. ASSERT(w # NIL);
  136. errors := 0;
  137. IF DoStep(WriteMBR) THEN CheckFile(mbrFile, "MBR file"); END;
  138. IF DoStep(Format) THEN CheckFile(bootloader, "Boot loader file "); CheckFile(bootfile, "Boot file"); END;
  139. IF DoStep(UpdateBootfile) THEN CheckFile(bootfile, "Boot file"); END;
  140. IF DoStep(SetConfig) & (configTable = NIL) THEN
  141. ShowError("No configurations strings set"); w.Ln;
  142. END;
  143. IF DoStep(InstallBootManager) THEN
  144. CheckFile(bootManMBR, "Boot Manager MBR file"); CheckFile(bootManRest, "Boot Manager Rest file");
  145. END;
  146. IF ~DoStep(Mount) THEN
  147. IF (disk.fs = NIL) OR ((disk.fs # NIL) & (partition < LEN(disk.fs)) & (disk.fs[partition] = NIL)) THEN
  148. ShowError("Disk is already mounted, but could not determine file system prefix"); w.Ln;
  149. END;
  150. END;
  151. IF DoStep(InstallPackages) & (packages # NIL) THEN
  152. packages.GetInstallSize(installSize, installSizeOnDisk, nofEntries);
  153. installSizeOnDisk := installSizeOnDisk DIV 1024 + 1;
  154. IF (installSizeOnDisk > SpaceAvailable()) THEN
  155. ShowError("Not enough disk space: "); w.Ln;
  156. w.String("Available disk space: "); w.Int(SpaceAvailable(), 0); w.String(" KB"); w.Ln;
  157. w.String("Required disk space: "); w.Int(installSizeOnDisk, 0); w.String(" KB"); w.Ln;
  158. END;
  159. END;
  160. w.Update;
  161. RETURN errors = 0;
  162. END CheckConfiguration;
  163. PROCEDURE ToStream*(w : Streams.Writer);
  164. VAR step : LONGINT;
  165. PROCEDURE ShowStep(CONST string : ARRAY OF CHAR);
  166. BEGIN
  167. INC(step);
  168. w.Int(step, 3); w.String(": "); w.String(string);
  169. END ShowStep;
  170. BEGIN
  171. ASSERT(w # NIL);
  172. w.String("To install A2 on partition "); w.String(diskpartString); w.String(", the following steps will be done:");
  173. w.Ln; w.Ln;
  174. step := 0;
  175. IF DoStep(WriteMBR)THEN ShowStep("Write MBR ("); w.String(mbrFile); w.String(")"); w.Ln; END;
  176. IF DoStep(CreatePartition) THEN ShowStep("Create partition of type 4C (AosFS)"); w.Ln; END;
  177. IF DoStep(ChangeType) THEN
  178. ShowStep("Change type of partition "); w.String(diskpartString); w.String(" from ");
  179. w.Hex(disk.table[partition].type, -2); w.String(" to "); w.Hex(AosPartitionType, -2); w.Ln;
  180. END;
  181. IF DoStep(Activate) THEN ShowStep("Set active flag of partiton "); w.String(diskpartString); w.Ln; END;
  182. IF DoStep(Format) THEN
  183. ShowStep("Format partiton "); w.String(diskpartString); w.String(" as AosFS (");
  184. w.String("Boot Loader: "); w.String(bootloader); w.String(", ");
  185. w.String("Boot File: "); w.String(bootfile); w.String(")");
  186. w.Ln;
  187. END;
  188. IF DoStep(UpdateBootfile) THEN
  189. ShowStep("Update boot file (Boot file: "); w.String(bootfile); w.String(")"); w.Ln;
  190. END;
  191. IF DoStep(SetConfig) THEN
  192. ShowStep("Set configuration strings"); w.Ln;
  193. END;
  194. IF DoStep(InstallBootManager) THEN
  195. ShowStep("Install Boot Manager into MBR ("); w.String(bootManMBR); w.String(", "); w.String(bootManRest);
  196. w.String(")"); w.Ln;
  197. END;
  198. IF DoStep(Mount) THEN
  199. ShowStep("Mounting partition "); w.String(diskpartString); w.Ln;
  200. END;
  201. IF DoStep(InstallPackages) THEN
  202. ShowStep("Installing packages"); w.Ln;
  203. END;
  204. IF DoStep(Unmount) THEN
  205. ShowStep("Ummount partition "); w.String(diskpartString); w.Ln;
  206. END;
  207. w.Update;
  208. END ToStream;
  209. PROCEDURE DisallowAllSteps;
  210. VAR i : LONGINT;
  211. BEGIN
  212. FOR i := 0 TO LEN(steps)-1 DO
  213. steps[i] := NotAllowed;
  214. END;
  215. END DisallowAllSteps;
  216. PROCEDURE DetectInstallSettings;
  217. BEGIN
  218. DisallowAllSteps;
  219. IF (Disks.Mounted IN disk.table[partition].flags) OR (Disks.Valid IN disk.table[0].flags) THEN
  220. steps[WriteMBR] := NotAllowed;
  221. ELSE
  222. steps[WriteMBR] := Mandatory;
  223. END;
  224. mbrFile := DefaultMBRFile;
  225. IF (disk.table[partition].type = Free) THEN
  226. steps[CreatePartition] := Mandatory;
  227. ELSE
  228. steps[CreatePartition] := NotAllowed;
  229. END;
  230. size := 0;
  231. IF ~(Disks.Mounted IN disk.table[partition].flags) & (disk.table[partition].type # Free) & (disk.table[partition].type # AosPartitionType) THEN
  232. steps[ChangeType] := Mandatory;
  233. ELSE
  234. steps[ChangeType] := NotAllowed;
  235. END;
  236. IF (Disks.Mounted IN disk.table[partition].flags) OR (Disks.Boot IN disk.table[partition].flags) THEN steps[Activate] := NotAllowed;
  237. ELSE
  238. IF (steps[WriteMBR] = Mandatory) OR ((steps[CreatePartition] = Mandatory) & (LEN(disk.table)=2)) THEN
  239. steps[Activate] := OptionalYes;
  240. ELSE
  241. steps[Activate] := OptionalNo;
  242. END;
  243. END;
  244. IF ~(Disks.Mounted IN disk.table[partition].flags) THEN
  245. steps[Format] := Mandatory;
  246. ELSE
  247. steps[Format] := NotAllowed;
  248. END;
  249. bootloader := DefaultBootLoader;
  250. IF ~DoStep(Format) THEN
  251. steps[UpdateBootfile] := OptionalYes;
  252. ELSE
  253. steps[UpdateBootfile] := OptionalNo;
  254. END;
  255. IF IsUsbDisk() THEN
  256. bootfile := DefaultUsbBootfile;
  257. ELSE
  258. bootfile := DefaultBootfile;
  259. END;
  260. IF DoStep(Format) THEN
  261. steps[SetConfig] := OptionalYes;
  262. ELSE
  263. steps[SetConfig] := OptionalNo;
  264. END;
  265. IF DoStep(WriteMBR) & IsUsbDisk() THEN
  266. steps[InstallBootManager] := OptionalYes;
  267. ELSE
  268. steps[InstallBootManager] := OptionalNo;
  269. END;
  270. bootManMBR := DefaultBootManMBR;
  271. bootManRest := DefaultBootManRest;
  272. mountPrefix := "";
  273. IF (Disks.Mounted IN disk.table[partition].flags) THEN
  274. steps[Mount] := NotAllowed;
  275. IF (disk.fs # NIL) & (partition < LEN(disk.fs)) & (disk.fs[partition] # NIL) THEN
  276. mountPrefix := disk.fs[partition].prefix;
  277. END;
  278. ELSE
  279. steps[Mount] := Mandatory;
  280. mountPrefix := GetPrefix();
  281. END;
  282. steps[InstallPackages] := OptionalNo;
  283. IF (Disks.Mounted IN disk.table[partition].flags) THEN
  284. steps[Unmount] := NotAllowed;
  285. ELSE
  286. steps[Unmount] := OptionalYes;
  287. END;
  288. END DetectInstallSettings;
  289. PROCEDURE Clone*() : Configuration;
  290. VAR c : Configuration; i : LONGINT;
  291. BEGIN
  292. NEW(c, disk, partition);
  293. FOR i := 0 TO LEN(c.steps)-1 DO c.steps[i] := steps[i]; END;
  294. c.mbrFile := mbrFile;
  295. c.size := size;
  296. c.bootloader := bootloader;
  297. c.bootfile := bootfile;
  298. c.configTable := configTable.Clone();
  299. c.bootManMBR := bootManMBR;
  300. c.bootManRest := bootManRest;
  301. c.mountPrefix := mountPrefix;
  302. c.packages := packages;
  303. RETURN c;
  304. END Clone;
  305. PROCEDURE SetPackages*(packages : Packages);
  306. BEGIN
  307. SELF.packages := packages;
  308. IF (packages # NIL) THEN
  309. steps[InstallPackages] := OptionalYes;
  310. ELSE
  311. steps[InstallPackages] := NotAllowed;
  312. END;
  313. END SetPackages;
  314. PROCEDURE &Init*(disk : PartitionsLib.Disk; partition : LONGINT);
  315. VAR nbr : ARRAY 8 OF CHAR;
  316. BEGIN
  317. ASSERT(disk.device # NIL);
  318. ASSERT((1 <= partition) & (partition < LEN(disk.table)));
  319. SELF.disk := disk; SELF.partition := partition;
  320. COPY(disk.device.name, diskpartString);
  321. Strings.Append(diskpartString, "#"); Strings.IntToStr(partition, nbr); Strings.Append(diskpartString, nbr);
  322. packages := NIL;
  323. NEW(configTable);
  324. DetectInstallSettings;
  325. END Init;
  326. END Configuration;
  327. TYPE
  328. Installer* = OBJECT(PartitionsLib.Operation)
  329. VAR
  330. (* parameters *)
  331. config : Configuration;
  332. currentStep, nofSteps : LONGINT;
  333. nofFiles : LONGINT;
  334. installLog : Streams.Writer;
  335. PROCEDURE SetInstallLog*(installLog : Streams.Writer);
  336. BEGIN
  337. ASSERT(installLog # NIL);
  338. SELF.installLog := installLog;
  339. END SetInstallLog;
  340. (** Write lock partition before this operation is running *)
  341. PROCEDURE Lock*() : BOOLEAN;
  342. BEGIN
  343. RETURN PartitionsLib.diskModel.AcquirePartition(disk, partition, PartitionsLib.WriterLock);
  344. END Lock;
  345. (** Release write lock *)
  346. PROCEDURE Unlock*;
  347. BEGIN
  348. PartitionsLib.diskModel.ReleasePartition(disk, partition);
  349. END Unlock;
  350. PROCEDURE SetParameters*(config : Configuration);
  351. BEGIN
  352. SELF.config := config;
  353. END SetParameters;
  354. PROCEDURE ValidParameters*() : BOOLEAN;
  355. BEGIN
  356. IF (config = NIL) THEN
  357. ReportError("No install configuration set");
  358. RETURN FALSE;
  359. (* ELSIF (Disks.ReadOnly IN disk.table[partition].flags) THEN
  360. ReportError("Cannot install A2 on read-only device");
  361. RETURN FALSE; *)
  362. ELSIF (Disks.Mounted IN disk.table[partition].flags) & (disk.table[partition].type # AosPartitionType) THEN
  363. ReportError("Partition is mounted but type is not 76");
  364. RETURN FALSE;
  365. ELSIF (partition = 0) THEN
  366. ReportError("A2 must be installed into partition != 0");
  367. RETURN FALSE;
  368. END;
  369. RETURN TRUE;
  370. END ValidParameters;
  371. PROCEDURE SetStep(CONST string : PartitionsLib.String);
  372. VAR caption : PartitionsLib.String; nbr : ARRAY 8 OF CHAR;
  373. BEGIN
  374. INC(currentStep);
  375. Strings.IntToStr(currentStep, caption); Strings.Append(caption, " of "); Strings.IntToStr(nofSteps, nbr); Strings.Append(caption, nbr);
  376. Strings.Append(caption, ": "); Strings.Append(caption, string);
  377. SetStatus(state.status, caption, 0, currentStep, 100, TRUE);
  378. END SetStep;
  379. PROCEDURE PackagesProgress(nofFilesExtracted : LONGINT);
  380. VAR progress : LONGINT;
  381. BEGIN
  382. IF nofFilesExtracted = nofFiles THEN
  383. progress := 100;
  384. ELSE
  385. progress := currentStep + ENTIER((100 - currentStep) * (nofFilesExtracted / nofFiles));
  386. END;
  387. SetCurrentProgress(progress);
  388. END PackagesProgress;
  389. PROCEDURE DoOperation*;
  390. VAR i : LONGINT; res : WORD;
  391. BEGIN
  392. ASSERT((config.disk.device = disk.device) & (config.partition = partition));
  393. installLog.String("Starting installation on partition "); installLog.String(diskpartString); installLog.String("..."); installLog.Ln; installLog.Update;
  394. currentStep := 0;
  395. nofSteps := config.GetNofSteps();
  396. IF Aborted() THEN ReportAbort; RETURN; END;
  397. IF config.DoStep(WriteMBR) THEN (* no MBR *)
  398. ASSERT(disk.table[0].flags * {Disks.Valid} = {});
  399. SetStep("Writing MBR");
  400. IF ~DoWriteMBR() THEN
  401. ReportError("Could not write MBR to disk");
  402. RETURN;
  403. END;
  404. END;
  405. IF Aborted() THEN ReportAbort; RETURN; END;
  406. IF config.DoStep(CreatePartition) THEN
  407. ASSERT(disk.table[partition].type = Free);
  408. SetStep("Creating partition");
  409. ASSERT(disk.device.openCount = 1);
  410. IF DoCreatePartition() THEN
  411. ASSERT((partition = 1));
  412. disk.device.Close(res);
  413. Disks.UpdatePartitionTable(disk.device, res);
  414. disk.device.Open(res);
  415. FOR i := 0 TO LEN(disk.device.table)-1 DO
  416. disk.table[i] := disk.device.table[i];
  417. END;
  418. ELSE
  419. ReportError("Could not create primary partition");
  420. RETURN;
  421. END;
  422. END;
  423. IF Aborted() THEN ReportAbort; RETURN; END;
  424. IF config.DoStep(ChangeType) THEN
  425. ASSERT(disk.table[partition].type # AosPartitionType);
  426. SetStep("Change partition type");
  427. IF ~DoChangePartitionTypeTo(disk.table[partition].type, AosPartitionType) THEN
  428. ReportError("Could not change partition type");
  429. RETURN;
  430. END;
  431. END;
  432. IF Aborted() THEN ReportAbort; RETURN; END;
  433. IF config.DoStep(Activate) & (disk.table[partition].flags * {Disks.Boot} = {}) THEN
  434. SetStep("Activate partition");
  435. IF ~DoActivatePartition() THEN
  436. ReportError("Could not set active flag");
  437. RETURN;
  438. END;
  439. END;
  440. IF Aborted() THEN ReportAbort; RETURN; END;
  441. IF config.DoStep(InstallBootManager) THEN
  442. IF ~DoInstallBootManager() THEN
  443. ReportError("Could not install boot manager");
  444. RETURN;
  445. END;
  446. END;
  447. IF Aborted() THEN ReportAbort; RETURN; END;
  448. IF config.DoStep(Format) THEN
  449. SetStep("Formatting partition");
  450. IF ~DoFormatPartition() THEN
  451. ReportError("Could not format the partition");
  452. RETURN;
  453. END;
  454. END;
  455. IF Aborted() THEN ReportAbort; RETURN; END;
  456. IF config.DoStep(UpdateBootfile) THEN
  457. SetStep("Updating boot file");
  458. IF ~DoUpdateBootFile() THEN
  459. ReportError("Could not update boot file");
  460. RETURN;
  461. END;
  462. END;
  463. IF Aborted() THEN ReportAbort; RETURN; END;
  464. IF config.DoStep(SetConfig) THEN
  465. SetStep("Setting configuration");
  466. IF ~DoSetConfiguration() THEN
  467. ReportError("Could not write configuration string");
  468. RETURN;
  469. END;
  470. END;
  471. IF Aborted() THEN ReportAbort; RETURN; END;
  472. IF config.DoStep(Mount) & (disk.table[partition].flags * {Disks.Mounted} = {}) THEN
  473. SetStep("Mounting partition");
  474. IF ~DoMountPartition() THEN
  475. ReportError("Could not mount the partition");
  476. RETURN;
  477. END;
  478. END;
  479. IF Aborted() THEN ReportAbort; RETURN; END;
  480. IF config.DoStep(InstallPackages) THEN
  481. SetStep("Installing packages");
  482. IF ~DoInstallPackages() THEN
  483. ReportError("Could not install packages");
  484. RETURN;
  485. END;
  486. END;
  487. IF Aborted() THEN ReportAbort; RETURN; END;
  488. IF config.DoStep(Unmount) THEN
  489. DoUnmount;
  490. END;
  491. SetCurrentProgress(100);
  492. installLog.String("Successfully installed on partition "); installLog.String(diskpartString); installLog.String("."); installLog.Update;
  493. END DoOperation;
  494. PROCEDURE DoInstallPackages() : BOOLEAN;
  495. VAR path : Files.FileName; ignore : LONGINT;
  496. BEGIN
  497. ASSERT(config.packages # NIL);
  498. installLog.String("Installing packages to "); installLog.String(config.mountPrefix); installLog.String(" ... "); installLog.Ln; installLog.Update;
  499. COPY(config.mountPrefix, path); Strings.Append(path, ":");
  500. config.packages.SetInstallLog(installLog);
  501. config.packages.SetReportProgressProc(PackagesProgress);
  502. config.packages.SetAbortedProc(Aborted);
  503. config.packages.GetInstallSize(ignore, ignore, nofFiles);
  504. config.packages.InstallPackages(path);
  505. RETURN TRUE;
  506. END DoInstallPackages;
  507. PROCEDURE DoWriteMBR() : BOOLEAN;
  508. VAR operation : PartitionsLib.WriteMBR;
  509. BEGIN
  510. installLog.String("Writing MBR to disk (MBR File: "); installLog.String(config.mbrFile); installLog.String(") ... "); installLog.Update;
  511. NEW(operation, disk, 0, out);
  512. operation.SetParent(SELF);
  513. operation.SetParameters(config.mbrFile, FALSE, FALSE);
  514. operation.SetBlockingStart;
  515. RETURN OperationDone(operation);
  516. END DoWriteMBR;
  517. PROCEDURE DoCreatePartition() : BOOLEAN;
  518. VAR operation : PartitionsLib.CreatePartition;
  519. BEGIN
  520. installLog.String("Creating partition... "); installLog.Update;
  521. NEW(operation, disk, partition, out);
  522. operation.SetParent(SELF);
  523. operation.SetParameters(999999, AosPartitionType, TRUE);
  524. operation.SetBlockingStart;
  525. RETURN OperationDone(operation);
  526. END DoCreatePartition;
  527. PROCEDURE DoChangePartitionTypeTo(oldType, newType : LONGINT) : BOOLEAN;
  528. VAR operation : PartitionsLib.ChangePartType;
  529. BEGIN
  530. installLog.String("Change partition type from "); installLog.Hex(oldType, 2); installLog.String("h to "); installLog.Hex(newType, 2);
  531. installLog.String("h ... "); installLog.Update;
  532. NEW(operation, disk, partition, out);
  533. operation.SetParent(SELF);
  534. operation.SetParameters(oldType, newType);
  535. operation.SetBlockingStart;
  536. RETURN OperationDone(operation);
  537. END DoChangePartitionTypeTo;
  538. PROCEDURE DoActivatePartition() : BOOLEAN;
  539. VAR operation : PartitionsLib.SetFlags;
  540. BEGIN
  541. installLog.String("Set active flag... "); installLog.Update;
  542. NEW(operation, disk, partition, out);
  543. operation.SetParent(SELF);
  544. operation.SetParameters(TRUE);
  545. operation.SetBlockingStart;
  546. RETURN OperationDone(operation);
  547. END DoActivatePartition;
  548. PROCEDURE DoInstallBootManager() : BOOLEAN;
  549. VAR operation : PartitionsLib.InstallBootManager;
  550. BEGIN
  551. installLog.String("Install Bluebottle Boot Manager..."); installLog.Update;
  552. NEW(operation, disk, 0, out);
  553. operation.SetParent(SELF);
  554. operation.SetParameters(config.bootManMBR, config.bootManRest);
  555. operation.SetBlockingStart;
  556. RETURN OperationDone(operation);
  557. END DoInstallBootManager;
  558. PROCEDURE DoFormatPartition() : BOOLEAN;
  559. VAR operation : PartitionsLib.FormatPartition;
  560. BEGIN
  561. installLog.String("Formatting partition (Boot Loader: "); installLog.String(config.bootloader);
  562. installLog.String(", Boot File: "); installLog.String(config.bootfile); installLog.String(") ... "); installLog.Update;
  563. NEW(operation, disk, partition, out);
  564. operation.SetParent(SELF);
  565. operation.SetParameters(AosFsName, config.bootfile, -2, 0);
  566. operation.SetBlockingStart;
  567. RETURN OperationDone(operation);
  568. END DoFormatPartition;
  569. PROCEDURE DoUpdateBootFile() : BOOLEAN;
  570. VAR operation : PartitionsLib.UpdateBootFile;
  571. BEGIN
  572. installLog.String("Updating boot file ("); installLog.String(config.bootfile); installLog.String(") ... "); installLog.Update;
  573. NEW(operation, disk, partition, out);
  574. operation.SetParent(SELF);
  575. operation.SetParameters(config.bootfile);
  576. operation.SetBlockingStart;
  577. RETURN OperationDone(operation);
  578. END DoUpdateBootFile;
  579. PROCEDURE DoSetConfiguration() : BOOLEAN;
  580. VAR
  581. operation : PartitionsLib.SetConfig; configString : Strings.String;
  582. bootString : ARRAY 128 OF CHAR;
  583. BEGIN
  584. installLog.String("Writing configuration strings (BootVol is "); installLog.String(diskpartString); installLog.String(") ... "); installLog.Update;
  585. IF (config.configTable = NIL) THEN ReportError("Configuration table is NIL"); RETURN FALSE; END;
  586. COPY(BootVolString, bootString);
  587. Strings.Append(bootString, diskpartString);
  588. config.configTable.SetValueOf(Strings.NewString("BootVol1"), Strings.NewString(bootString));
  589. configString := config.configTable.GetAsString();
  590. NEW(operation, disk, partition, out);
  591. operation.SetParent(SELF);
  592. operation.SetParameters(configString, 0);
  593. operation.SetBlockingStart;
  594. RETURN OperationDone(operation);
  595. END DoSetConfiguration;
  596. PROCEDURE DoMountPartition() : BOOLEAN;
  597. VAR operation : PartitionsLib.Mount;
  598. BEGIN
  599. installLog.String("Mounting partition... "); installLog.Update;
  600. NEW(operation, disk, partition, out);
  601. operation.SetParent(SELF);
  602. operation.SetParameters(config.mountPrefix, "AosFS", "", "");
  603. operation.SetBlockingStart;
  604. RETURN OperationDone(operation);
  605. END DoMountPartition;
  606. PROCEDURE DoUnmount;
  607. VAR context : Commands.Context; arg : Streams.StringReader; msg : ARRAY 128 OF CHAR; res : WORD;
  608. BEGIN
  609. installLog.String("Unmounting "); installLog.String(diskpartString); installLog.String("... "); installLog.Update;
  610. NEW(arg, LEN(config.mountPrefix)); arg.SetRaw(config.mountPrefix, 0, LEN(config.mountPrefix));
  611. NEW(context, NIL, arg, NIL, NIL, SELF);
  612. Commands.Activate("FSTools.Unmount", context, {Commands.Wait}, res, msg);
  613. IF (res = Commands.Ok) THEN
  614. installLog.String("done.");
  615. ELSE
  616. installLog.String("failed");
  617. installLog.String(" ("); installLog.String(msg); installLog.String(")");
  618. END;
  619. installLog.Ln;
  620. installLog.Update;
  621. END DoUnmount;
  622. PROCEDURE OperationDone(operation : PartitionsLib.Operation) : BOOLEAN;
  623. VAR noErrors : BOOLEAN; state : PartitionsLib.OperationState; errors: Strings.String;
  624. BEGIN
  625. state := operation.GetState();
  626. noErrors := (PartitionsLib.StatusFinished IN state.status) & (state.errorCount = 0);
  627. IF noErrors THEN
  628. installLog.String("done."); installLog.Ln;
  629. ELSE
  630. installLog.Ln;
  631. errors := operation.GetErrors (); installLog.String(errors^);
  632. installLog.Ln;
  633. END;
  634. installLog.Update;
  635. RETURN noErrors;
  636. END OperationDone;
  637. PROCEDURE ReportAbort;
  638. BEGIN
  639. installLog.String("Installation aborted by user."); installLog.Ln; installLog.Update;
  640. END ReportAbort;
  641. PROCEDURE &Init*(disk :PartitionsLib.Disk; partition : LONGINT; out : Streams.Writer);
  642. BEGIN
  643. Init^(disk, partition, out);
  644. name := "Installer"; desc := "Install A2 on partition"; locktype := PartitionsLib.WriterLock;
  645. NEW(installLog, KernelLog.Send, 128);
  646. END Init;
  647. END Installer;
  648. TYPE
  649. ReportProgressProc = PROCEDURE {DELEGATE} (nofFilesExtracted : LONGINT);
  650. AbortedProc = PROCEDURE {DELEGATE} () : BOOLEAN;
  651. ReportErrorProc = PROCEDURE {DELEGATE} (CONST msg : ARRAY OF CHAR);
  652. Package* = OBJECT
  653. VAR
  654. number- : LONGINT;
  655. (** Shall this package be installed? *)
  656. install- : BOOLEAN;
  657. installType- : LONGINT; (* Mandatory, OptionalYes, OptionalNo, NotAllowed *)
  658. filename- : XML.String;
  659. file- : Files.File;
  660. name-, description- : XML.String;
  661. (* Number of files contained in the package *)
  662. nofEntries- : LONGINT;
  663. (* Size of all files in package in bytes when extracted *)
  664. size- : LONGINT;
  665. (* size plus overhead introduced with Files file system (conservative approximation) *)
  666. sizeOnDisk- : LONGINT;
  667. user* : ANY;
  668. next : Package;
  669. (** Set his package to be installed or not. *)
  670. PROCEDURE SetInstall*(install : BOOLEAN; VAR msg : ARRAY OF CHAR) : BOOLEAN;
  671. BEGIN
  672. msg := "";
  673. IF install THEN
  674. IF (file = NIL) THEN
  675. msg := "File "; Strings.Append(msg, filename^); Strings.Append(msg, " not found");
  676. RETURN FALSE;
  677. ELSIF (installType = NotAllowed) THEN
  678. msg := "Installation of this package is not allowed";
  679. RETURN FALSE;
  680. END;
  681. ELSE
  682. IF (installType = Mandatory) THEN
  683. msg := "This package is required";
  684. RETURN FALSE;
  685. END;
  686. END;
  687. SELF.install := install;
  688. RETURN TRUE;
  689. END SetInstall;
  690. PROCEDURE Parse(p : XML.Element; error : Streams.Writer) : BOOLEAN;
  691. VAR nofErrors : LONGINT;
  692. BEGIN
  693. nofErrors := 0;
  694. number := GetXmlNumber(p, XmlPackageNumber);
  695. IF (number = -1) THEN
  696. error.String("Package number attribute not found"); error.Ln;
  697. INC(nofErrors);
  698. ELSIF (number < 1) OR (MaxPackages < number) THEN
  699. error.String("Package number invalid"); error.Ln;
  700. INC(nofErrors);
  701. END;
  702. filename := p.GetAttributeValue(XmlPackageFilename);
  703. IF (filename = NIL) THEN
  704. error.String("Filename attribute not found"); error.Ln;
  705. INC(nofErrors);
  706. ELSE
  707. file := Files.Old(filename^);
  708. END;
  709. name:= p.GetAttributeValue(XmlPackageName);
  710. IF (name = NIL) THEN
  711. name := Strings.NewString("NoName");
  712. END;
  713. description := p.GetAttributeValue(XmlPackageDescription);
  714. IF (description = NIL) THEN
  715. description := Strings.NewString("No Description Available");
  716. END;
  717. installType := GetInstallType(p);
  718. IF (installType = Invalid) THEN installType := OptionalNo; END;
  719. install := TRUE;
  720. IF (installType = OptionalNo) OR (installType = NotAllowed) OR (file = NIL) THEN
  721. install := FALSE;
  722. END;
  723. RETURN (nofErrors = 0);
  724. END Parse;
  725. PROCEDURE Show;
  726. BEGIN
  727. KernelLog.String("Package Nr "); KernelLog.Int(number, 0); KernelLog.String(": ");
  728. KernelLog.String(name^); KernelLog.String(" ("); KernelLog.String(description^); KernelLog.String(") ");
  729. KernelLog.String(", Filename: "); KernelLog.String(filename^);
  730. KernelLog.String(", installType: "); KernelLog.Int(installType, 0);
  731. KernelLog.Ln;
  732. END Show;
  733. PROCEDURE &Init*;
  734. BEGIN
  735. number := -1; install := FALSE;
  736. filename := NIL; file := NIL;
  737. name := NIL; description := NIL;
  738. nofEntries := 0; size := 0; sizeOnDisk := 0;
  739. user := NIL; next := NIL;
  740. END Init;
  741. END Package;
  742. PackageArray*= POINTER TO ARRAY OF Package;
  743. TYPE
  744. Packages* = OBJECT
  745. VAR
  746. hasErrors : BOOLEAN;
  747. ReportError : ReportErrorProc;
  748. (* Head and tail of package list *)
  749. head, tail : Package;
  750. info : Streams.Writer;
  751. path : Files.FileName;
  752. nofFilesExtracted : LONGINT;
  753. reportProgress : ReportProgressProc;
  754. Aborted : AbortedProc;
  755. PROCEDURE GetNofPackages() : LONGINT;
  756. VAR nofPackages : LONGINT; package : Package;
  757. BEGIN
  758. nofPackages := 0;
  759. package := head;
  760. WHILE (package # NIL) DO INC(nofPackages); package := package.next; END;
  761. RETURN nofPackages;
  762. END GetNofPackages;
  763. PROCEDURE GetPackages*() : PackageArray;
  764. VAR result : PackageArray; package : Package; nofPackages, i : LONGINT;
  765. BEGIN
  766. result := NIL;
  767. nofPackages := GetNofPackages();
  768. IF (nofPackages > 0) THEN
  769. NEW(result, nofPackages);
  770. package := head;
  771. i := 0;
  772. WHILE (package # NIL) DO
  773. result[i] := package; INC(i);
  774. package := package.next;
  775. END;
  776. END;
  777. RETURN result;
  778. END GetPackages;
  779. PROCEDURE ReportProgress(nofFilesExtracted : LONGINT);
  780. BEGIN
  781. IF (reportProgress # NIL) THEN reportProgress(nofFilesExtracted); END;
  782. END ReportProgress;
  783. PROCEDURE ExtractEntry(zip: AosUnzip.ZipFile; entry: AosUnzip.Entry; CONST name: ARRAY OF CHAR; VAR res : WORD);
  784. VAR file: Files.File; w : Files.Writer; string : ARRAY 256 OF CHAR;
  785. BEGIN
  786. res := 0;
  787. file := Files.New(name);
  788. IF file = NIL THEN
  789. string := "Could not create file "; Strings.Append(string, name);
  790. ReportError(string); res := 99;
  791. RETURN
  792. END;
  793. Files.OpenWriter(w, file, 0);
  794. zip.Extract(entry, w, res);
  795. IF res = Streams.Ok THEN
  796. w.Update(); Files.Register(file);
  797. ELSE
  798. string := "Extracting "; Strings.Append(string, name); Strings.Append(string, " failed");
  799. ReportError(string); res := 99;
  800. END;
  801. END ExtractEntry;
  802. PROCEDURE Unzip(zipFile : AosUnzip.ZipFile) : BOOLEAN;
  803. VAR e : AosUnzip.Entry; res : WORD; name : Files.FileName;
  804. BEGIN
  805. res := 0;
  806. e := zipFile.GetFirst();
  807. WHILE e # NIL DO
  808. IF (path # "") THEN
  809. COPY(path, name); Strings.Append(name, e.name^)
  810. ELSE
  811. COPY(e.name^, name)
  812. END;
  813. ExtractEntry(zipFile, e, name, res);
  814. IF res # 0 THEN RETURN FALSE; END;
  815. INC(nofFilesExtracted);
  816. ReportProgress(nofFilesExtracted);
  817. e := zipFile.GetNext(e);
  818. IF Aborted() THEN e := NIL; END;
  819. END;
  820. RETURN res = 0;
  821. END Unzip;
  822. PROCEDURE OpenZipFile(CONST filename : ARRAY OF CHAR; reportErrors : BOOLEAN) : AosUnzip.ZipFile;
  823. VAR file : Files.File; res : WORD; string : ARRAY 256 OF CHAR; zipFile : AosUnzip.ZipFile;
  824. BEGIN
  825. zipFile := NIL;
  826. file := Files.Old(filename);
  827. IF (file # NIL) THEN
  828. NEW(zipFile, file, res);
  829. IF (res # Streams.Ok) THEN
  830. zipFile := NIL;
  831. COPY(filename, string); Strings.Append(string, " is not a valid ZIP file");
  832. ReportError(string);
  833. END;
  834. ELSIF reportErrors THEN
  835. string := "ZIP file "; Strings.Append(string, filename); Strings.Append(string, " not found");
  836. ReportError(string);
  837. END;
  838. RETURN zipFile;
  839. END OpenZipFile;
  840. PROCEDURE GetPackageSizes*;
  841. VAR package : Package; zipFile : AosUnzip.ZipFile;
  842. PROCEDURE GetSizes(zipFile : AosUnzip.ZipFile; VAR size, sizeOnDisk : LONGINT);
  843. VAR e : AosUnzip.Entry;
  844. BEGIN
  845. size := 0; sizeOnDisk := 0;
  846. e := zipFile.GetFirst();
  847. WHILE e # NIL DO
  848. size := size + e.size;
  849. (* Round up file size to file system block size and add an constant representing the overhead of meta data per file *)
  850. sizeOnDisk := sizeOnDisk + e.size + (BlockSize - (e.size MOD BlockSize)) + FsMetaOverheadPerFile;
  851. e := zipFile.GetNext(e)
  852. END;
  853. END GetSizes;
  854. BEGIN
  855. package := head;
  856. WHILE (package # NIL) DO
  857. zipFile := OpenZipFile(package.filename^, FALSE);
  858. IF (zipFile # NIL) THEN
  859. package.nofEntries := zipFile.NoOfEntries();
  860. GetSizes(zipFile, package.size, package.sizeOnDisk);
  861. END;
  862. package := package.next;
  863. END;
  864. END GetPackageSizes;
  865. PROCEDURE GetInstallSize*(VAR size, sizeOnDisk, nofEntries : LONGINT);
  866. VAR package : Package;
  867. BEGIN
  868. size := 0; sizeOnDisk := 0; nofEntries := 0;
  869. package := head;
  870. WHILE (package # NIL) DO
  871. IF package.install THEN
  872. size := size + package.size;
  873. sizeOnDisk := sizeOnDisk + package.sizeOnDisk;
  874. nofEntries := nofEntries + package.nofEntries;
  875. END;
  876. package := package.next;
  877. END;
  878. size := size DIV 1024;
  879. END GetInstallSize;
  880. PROCEDURE InstallPackages*(CONST targetPath : ARRAY OF CHAR);
  881. VAR package : Package; zipFile : AosUnzip.ZipFile; oldNofFilesExtracted : LONGINT;
  882. BEGIN
  883. nofFilesExtracted := 0;
  884. COPY(targetPath, path);
  885. package := head;
  886. WHILE (package # NIL) DO
  887. IF package.install THEN
  888. zipFile := OpenZipFile(package.filename^, TRUE);
  889. IF (zipFile # NIL) THEN
  890. oldNofFilesExtracted := nofFilesExtracted;
  891. info.String("Extracting package "); info.String(package.filename^); info.String("... "); info.Update;
  892. IF ~Unzip(zipFile) THEN
  893. ReportError("ERROR");
  894. END;
  895. info.Int(nofFilesExtracted - oldNofFilesExtracted, 0); info.String(" files unpacked, done."); info.Ln; info.Update;
  896. END;
  897. END;
  898. package := package.next;
  899. IF Aborted() THEN package := NIL; END;
  900. END;
  901. END InstallPackages;
  902. PROCEDURE DefaultReportError(CONST msg : ARRAY OF CHAR);
  903. BEGIN
  904. KernelLog.String("Installer.Packages: Error: "); KernelLog.String(msg); KernelLog.Ln;
  905. END DefaultReportError;
  906. PROCEDURE SetInstallLog*(info : Streams.Writer);
  907. BEGIN
  908. ASSERT(info # NIL);
  909. SELF.info := info;
  910. END SetInstallLog;
  911. PROCEDURE SetReportErrorProc(proc : ReportErrorProc);
  912. BEGIN
  913. ReportError := proc;
  914. END SetReportErrorProc;
  915. PROCEDURE SetReportProgressProc(proc : ReportProgressProc);
  916. BEGIN
  917. reportProgress := proc;
  918. END SetReportProgressProc;
  919. PROCEDURE SetAbortedProc(proc : AbortedProc);
  920. BEGIN
  921. ASSERT(proc # NIL);
  922. Aborted := proc;
  923. END SetAbortedProc;
  924. (* Report errors while parsing *)
  925. PROCEDURE Error(pos, line, row: LONGINT; CONST msg: ARRAY OF CHAR);
  926. VAR string : ARRAY 256 OF CHAR; nbr : ARRAY 16 OF CHAR;
  927. BEGIN
  928. string := "Parse error at pos "; Strings.IntToStr(pos, nbr); Strings.Append(string, nbr);
  929. Strings.Append(string, " in line "); Strings.IntToStr(line, nbr); Strings.Append(string, nbr);
  930. Strings.Append(string, " row "); Strings.IntToStr(row, nbr); Strings.Append(string, nbr);
  931. Strings.Append(string, msg);
  932. ReportError(msg);
  933. hasErrors := TRUE
  934. END Error;
  935. PROCEDURE OpenPackages*(CONST name : ARRAY OF CHAR; error : Streams.Writer) : BOOLEAN;
  936. VAR
  937. reader : Streams.Reader;
  938. scanner : XMLScanner.Scanner; parser : XMLParser.Parser; doc : XML.Document;
  939. BEGIN
  940. ASSERT(error # NIL);
  941. hasErrors := FALSE;
  942. reader := Codecs.OpenInputStream(name);
  943. IF reader # NIL THEN
  944. NEW(scanner, reader); scanner.reportError := Error;
  945. NEW(parser, scanner); parser.reportError := Error;
  946. doc := parser.Parse();
  947. IF ~hasErrors THEN
  948. head := ParsePackages(doc, error);
  949. IF (head # NIL) THEN
  950. RETURN TRUE;
  951. END;
  952. ELSE
  953. error.String("XML parsing error(s) occured"); error.Ln;
  954. END;
  955. ELSE
  956. error.String("XML file '"); error.String(name); error.String("' not found"); error.Ln;
  957. END;
  958. RETURN FALSE;
  959. END OpenPackages;
  960. PROCEDURE ParsePackages(document : XML.Document; error : Streams.Writer) : Package;
  961. VAR
  962. enum : XMLObjects.Enumerator; e : XML.Element; p : ANY; s : XML.String;
  963. package : Package;
  964. BEGIN
  965. ASSERT(error # NIL);
  966. head := NIL; tail := NIL;
  967. e := document.GetRoot(); enum := e.GetContents();
  968. WHILE enum.HasMoreElements() DO
  969. p := enum.GetNext();
  970. IF p IS XML.Element THEN
  971. e := p(XML.Element); s := e.GetName();
  972. IF (s # NIL) & (s^ = XmlPackage) THEN
  973. NEW(package);
  974. IF package.Parse(e, error) THEN
  975. package.next := NIL;
  976. IF (head = NIL) THEN
  977. head := package; tail := package;
  978. ELSE
  979. tail.next := package; tail := package;
  980. END;
  981. ELSE
  982. head := NIL; tail := NIL;
  983. RETURN NIL;
  984. END;
  985. END;
  986. END;
  987. END;
  988. RETURN head;
  989. END ParsePackages;
  990. PROCEDURE CheckPackages() : BOOLEAN;
  991. VAR package : Package; errors : LONGINT;
  992. PROCEDURE Error(packagename : XML.String; CONST msg1, msg2 : ARRAY OF CHAR);
  993. VAR string : ARRAY 256 OF CHAR;
  994. BEGIN
  995. string := "Package ";
  996. IF (packagename # NIL) THEN Strings.Append(string, packagename^) ELSE Strings.Append(string, "Unknown"); END;
  997. Strings.Append(string, ": "); Strings.Append(string, msg1); Strings.Append(string, msg2);
  998. ReportError(string);
  999. INC(errors);
  1000. END Error;
  1001. BEGIN
  1002. errors := 0;
  1003. IF (head # NIL) THEN
  1004. package := head;
  1005. WHILE (package # NIL) DO
  1006. IF (package.install) & (package.file = NIL) THEN
  1007. Error(package.name, "File not found; ", package.filename^);
  1008. END;
  1009. package := package.next;
  1010. END;
  1011. ELSE
  1012. ReportError("No packages found"); INC(errors);
  1013. END;
  1014. RETURN errors = 0;
  1015. END CheckPackages;
  1016. PROCEDURE Show;
  1017. VAR package : Package;
  1018. BEGIN
  1019. KernelLog.String("Packages: "); KernelLog.Ln;
  1020. IF (head # NIL) THEN
  1021. package := head;
  1022. WHILE (package # NIL) DO
  1023. package.Show; package := package.next;
  1024. END;
  1025. ELSE
  1026. KernelLog.String("No packages loaded."); KernelLog.Ln;
  1027. END;
  1028. END Show;
  1029. PROCEDURE DefaultAborted() : BOOLEAN;
  1030. BEGIN
  1031. RETURN FALSE;
  1032. END DefaultAborted;
  1033. PROCEDURE &Init*;
  1034. BEGIN
  1035. SELF.Aborted := DefaultAborted;
  1036. SetReportErrorProc(DefaultReportError);
  1037. NEW(info, KernelLog.Send, 256);
  1038. END Init;
  1039. END Packages;
  1040. VAR
  1041. suffix : LONGINT;
  1042. PROCEDURE FileExists(CONST filename : ARRAY OF CHAR) : BOOLEAN;
  1043. VAR file : Files.File;
  1044. BEGIN
  1045. file := Files.Old(filename);
  1046. RETURN file # NIL;
  1047. END FileExists;
  1048. PROCEDURE GetInstallType(p : XML.Element) : LONGINT;
  1049. VAR installType : LONGINT; string : XML.String;
  1050. BEGIN
  1051. ASSERT(p # NIL);
  1052. installType := OptionalYes;
  1053. string := p.GetAttributeValue(XmlPackageInstall);
  1054. IF (string # NIL) THEN
  1055. Strings.UpperCase(string^);
  1056. IF (string^ = XmlInstallYes) THEN installType := OptionalYes;
  1057. ELSIF (string^ = XmlInstallNo) THEN installType := OptionalNo;
  1058. ELSIF (string^ = XmlInstallRequired) THEN installType := Mandatory;
  1059. END;
  1060. END;
  1061. RETURN installType;
  1062. END GetInstallType;
  1063. (* Returns -1 in case that the attribute has not been found *)
  1064. PROCEDURE GetXmlNumber(p : XML.Element; CONST attributeName : ARRAY OF CHAR) : LONGINT;
  1065. VAR number : LONGINT; string : XML.String;
  1066. BEGIN
  1067. ASSERT(p # NIL);
  1068. number := -1;
  1069. string := p.GetAttributeValue(attributeName);
  1070. IF (string # NIL) THEN
  1071. Strings.StrToInt(string^, number);
  1072. END;
  1073. RETURN number;
  1074. END GetXmlNumber;
  1075. PROCEDURE GetPrefix() : Files.Prefix;
  1076. VAR prefix : Files.Prefix; nbr : ARRAY 8 OF CHAR;
  1077. BEGIN {EXCLUSIVE}
  1078. COPY(DefaultPrefix, prefix);
  1079. Strings.IntToStr(suffix, nbr);
  1080. Strings.Append(prefix, nbr);
  1081. INC(suffix);
  1082. RETURN prefix;
  1083. END GetPrefix;
  1084. PROCEDURE TestPackages*(context : Commands.Context);
  1085. VAR
  1086. filename : Files.FileName;
  1087. packages : Packages;
  1088. BEGIN
  1089. context.arg.SkipWhitespace; context.arg.String(filename);
  1090. context.out.String("Test packages object for file "); context.out.String(filename); context.out.String("... "); context.out.Ln;
  1091. NEW(packages);
  1092. IF packages.OpenPackages(filename, context.error) THEN
  1093. IF packages.CheckPackages() THEN
  1094. packages.Show;
  1095. ELSE
  1096. context.error.String("Package check failed."); context.error.Ln;
  1097. END;
  1098. ELSE
  1099. context.error.String("Could not open packages"); context.error.Ln;
  1100. END;
  1101. END TestPackages;
  1102. (** Quick-install the system on specified partition *)
  1103. PROCEDURE Install*(context : Commands.Context); (** dev#part ~ *)
  1104. VAR selection : PartitionsLib.Selection; installer : Installer;
  1105. BEGIN
  1106. IF Partitions.GetSelection(context, FALSE, selection) THEN
  1107. NEW(installer, selection.disk, selection.partition, context.out);
  1108. (* installer.SetParameters(); *)
  1109. installer.SetStart;
  1110. ELSE (* skip; error written to <w> by ScanOpenPart *)
  1111. END;
  1112. END Install;
  1113. END Installer.
  1114. Installer.TestPackages Packages.XML ~
  1115. System.Free Installer ~
  1116. System.FreeDownTo Installer ~
  1117. AosTar.Create Install.Tar
  1118. Installer.Mod WMInstaller.Mod
  1119. PartitionsLib.Mod Partitions.Mod WMPartitions.Mod
  1120. WMPartitionsComponents.Mod
  1121. InstallerPackages.XML
  1122. ~