GCC 4.3.x fixes for cabman and sysreg
[reactos.git] / reactos / tools / sysreg / rosboot_test.cpp
1
2 /* $Id$
3 *
4 * PROJECT: System regression tool for ReactOS
5 * LICENSE: GPL - See COPYING in the top level directory
6 * FILE: tools/sysreg/conf_parser.h
7 * PURPOSE: ReactOS boot test
8 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
9 */
10
11
12 #include "rosboot_test.h"
13
14 namespace Sysreg_
15 {
16 using std::vector;
17 using System_::PipeReader;
18 using System_::NamedPipeReader;
19 /* using System_::SymbolFile; */
20 using System_::FileReader;
21 using System_::OsSupport;
22 using System_::EnvironmentVariable;
23
24 #ifdef UNICODE
25 using std::wofstream;
26 typedef wofstream ofstream;
27 #else
28 using std::ofstream;
29 #endif
30
31 string RosBootTest::ROS_EMU_TYPE= "ROS_EMU_TYPE";
32 string RosBootTest::EMU_TYPE_QEMU = "qemu";
33 string RosBootTest::EMU_TYPE_VMWARE = "vmware";
34 string RosBootTest::EMU_TYPE_XEN = "xen";
35 string RosBootTest::ROS_HDD_IMAGE= "ROS_HDD_IMAGE";
36 string RosBootTest::ROS_CD_IMAGE = "ROS_CD_IMAGE";
37 string RosBootTest::ROS_MAX_TIME = "ROS_MAX_TIME";
38 string RosBootTest::ROS_LOG_FILE = "ROS_LOG_FILE";
39 string RosBootTest::ROS_SYM_DIR = "ROS_SYM_DIR";
40 string RosBootTest::ROS_DELAY_READ = "ROS_DELAY_READ";
41 string RosBootTest::ROS_SYSREG_CHECKPOINT = "SYSREG_CHECKPOINT:";
42 string RosBootTest::ROS_CRITICAL_IMAGE = "ROS_CRITICAL_IMAGE";
43 string RosBootTest::ROS_EMU_KILL = "ROS_EMU_KILL";
44 string RosBootTest::ROS_EMU_MEM = "ROS_EMU_MEM";
45 string RosBootTest::ROS_BOOT_CMD = "ROS_BOOT_CMD";
46 string RosBootTest::XEN_CONFIG_FILE = "XEN_CONFIG_FILE";
47 string RosBootTest::XEN_CONFIG_NAME = "XEN_CONFIG_NAME";
48
49 #ifdef __LINUX__
50 string RosBootTest::ROS_EMU_PATH = "ROS_EMU_PATH_LIN";
51 #else
52 string RosBootTest::ROS_EMU_PATH = "ROS_EMU_PATH_WIN";
53 #endif
54
55 //---------------------------------------------------------------------------------------
56 RosBootTest::RosBootTest() : m_MaxTime(65), m_DelayRead(0)
57 {
58
59 }
60
61 //---------------------------------------------------------------------------------------
62 RosBootTest::~RosBootTest()
63 {
64
65 }
66 //---------------------------------------------------------------------------------------
67 bool RosBootTest::executeBootCmd()
68 {
69 int numargs = 0;
70 const char * args[128];
71 char * pBuf;
72 char szBuffer[128];
73
74 pBuf = (char*)m_BootCmd.c_str ();
75 if (pBuf)
76 {
77 pBuf = strtok(pBuf, " ");
78 while(pBuf != NULL)
79 {
80 if (!numargs)
81 strcpy(szBuffer, pBuf);
82
83 args[numargs] = pBuf;
84 numargs++;
85 pBuf = strtok(NULL, " ");
86 }
87 args[numargs++] = 0;
88 }
89 else
90 {
91 strcpy(szBuffer, pBuf);
92 }
93 m_Pid = OsSupport::createProcess (szBuffer, numargs-1, args, false);
94 if (!m_Pid)
95 {
96 cerr << "Error: failed to launch boot cmd " << m_BootCmd << endl;
97 return false;
98 }
99
100 return true;
101 }
102 //---------------------------------------------------------------------------------------
103 void RosBootTest::delayRead()
104 {
105 if (m_DelayRead)
106 {
107 ///
108 /// delay reading until emulator is ready
109 ///
110
111 OsSupport::delayExecution(m_DelayRead);
112 }
113 }
114 //---------------------------------------------------------------------------------------
115 void RosBootTest::getDefaultHDDImage(string & img)
116 {
117 img = "output-i386";
118
119 EnvironmentVariable::getValue("ROS_OUTPUT", img);
120 #ifdef __LINUX__
121 img += "/ros.hd";
122 #else
123 img += "\\ros.hd";
124 #endif
125 }
126 //---------------------------------------------------------------------------------------
127 bool RosBootTest::isFileExisting(string output)
128 {
129 FILE * file;
130 file = fopen(output.c_str(), "r");
131
132 if (file)
133 {
134 /* the file exists */
135 fclose(file);
136 return true;
137 }
138 return false;
139 }
140
141 //---------------------------------------------------------------------------------------
142 bool RosBootTest::isDefaultHDDImageExisting()
143 {
144 string img;
145
146 getDefaultHDDImage(img);
147 return isFileExisting(img);
148 }
149
150 //---------------------------------------------------------------------------------------
151 bool RosBootTest::createHDDImage(string image)
152 {
153
154 string qemuimgdir;
155 if (!getQemuDir(qemuimgdir))
156 {
157 cerr << "Error: failed to retrieve qemu directory path" << endl;
158 return false;
159 }
160
161
162 #ifdef __LINUX__
163 qemuimgdir += "/qemu-img";
164
165 #else
166 qemuimgdir += "\\qemu-img.exe";
167 #endif
168
169 if (!isFileExisting(qemuimgdir))
170 {
171 cerr << "Error: ROS_EMU_PATH must contain the path to qemu and qemu-img " << qemuimgdir << endl;
172 return false;
173 }
174 remove(image.c_str ());
175
176 const char * options[] = {NULL,
177 "create",
178 "-f",
179 #ifdef __LINUX__
180 "raw",
181 #else
182 "vmdk",
183 #endif
184 NULL,
185 "100M",
186 NULL
187 };
188
189
190 options[0] = qemuimgdir.c_str();
191 options[4] = image.c_str();
192
193 cerr << "Creating HDD Image ..." << image << endl;
194 OsSupport::createProcess (qemuimgdir.c_str(), 6, options, true);
195 if (isFileExisting(image))
196 {
197 m_HDDImage = image;
198 return true;
199 }
200 return false;
201 }
202 //----------------------------------------------------------------------------------------
203 bool RosBootTest::isQemuPathValid()
204 {
205 string qemupath;
206
207 if (m_BootCmd.length())
208 {
209 /* the boot cmd is already provided
210 * check if path to qemu is valid
211 */
212 string::size_type pos = m_BootCmd.find_first_of(" ");
213 if (pos == string::npos)
214 {
215 /* the bootcmd is certainly not valid */
216 return false;
217 }
218 qemupath = m_BootCmd.substr(0, pos);
219 }
220 else
221 {
222 /* the qemu path is provided ROS_EMU_PATH variable */
223 qemupath = m_EmuPath;
224 }
225
226
227 return isFileExisting(qemupath);
228 }
229 //----------------------------------------------------------------------------------------
230 bool RosBootTest::hasQemuNoRebootOption()
231 {
232 ///
233 /// FIXME
234 /// extract version
235 ///
236
237 return true;
238 }
239 //----------------------------------------------------------------------------------------
240 bool RosBootTest::getQemuDir(string & qemupath)
241 {
242 string::size_type pos;
243
244 #ifdef __LINUX__
245 pos = m_EmuPath.find_last_of("/");
246 #else
247 pos = m_EmuPath.find_last_of("\\");
248 #endif
249 if (pos == string::npos)
250 {
251 cerr << "Error: ROS_EMU_PATH is invalid!!!" << endl;
252 return false;
253 }
254 qemupath = m_EmuPath.substr(0, pos);
255 return true;
256 }
257 //----------------------------------------------------------------------------------------
258 bool RosBootTest::createBootCmd()
259 {
260 string pipe;
261 string qemudir;
262 char pipename[] = "qemuXXXXXX";
263 if (m_MaxMem.length() == 0)
264 {
265 /* set default memory size to 64M */
266 m_MaxMem = "64";
267 }
268
269 #ifdef __LINUX__
270
271 if (mktemp(pipename))
272 {
273 string temp = pipename;
274 m_Src = "/tmp/" + temp;
275 pipe = "pipe:" + m_Src;
276 }
277 else
278 {
279
280 pipe = "pipe:/tmp/qemu";
281 m_Src = "/tmp/qemu";
282 }
283
284 qemudir = "/usr/share/qemu";
285 m_DebugPort = "pipe";
286 #else
287 if (_mktemp(pipename))
288 {
289 string temp = pipename;
290 pipe = "pipe:" + temp;
291 m_Src = "\\\\.\\pipe\\" + temp;
292 }
293 else
294 {
295 pipe = "pipe:qemu";
296 m_Src = "\\\\.\\pipe\\qemu";
297 }
298 m_DebugPort = "pipe";
299
300 if (!getQemuDir(qemudir))
301 {
302 return false;
303 }
304 #endif
305
306
307 m_BootCmd = m_EmuPath + " -L " + qemudir + " -m " + m_MaxMem + " -serial " + pipe;
308
309 if (m_CDImage.length())
310 {
311 /* boot from cdrom */
312 m_BootCmd += " -boot d -cdrom " + m_CDImage;
313
314 if (m_HDDImage.length ())
315 {
316 /* add disk when specified */
317 m_BootCmd += " -hda " + m_HDDImage;
318 }
319
320 }
321 else if (m_HDDImage.length ())
322 {
323 /* boot from hdd */
324 m_BootCmd += " -boot c -hda " + m_HDDImage;
325 }
326 else
327 {
328 /*
329 * no boot device provided
330 */
331 cerr << "Error: no bootdevice provided" << endl;
332 return false;
333 }
334
335 #ifdef __LINUX__
336 /* on linux we need get pid in order to be able
337 * to terminate the emulator in case of errors
338 * on windows we can get pid as return of CreateProcess
339 */
340 m_PidFile = "output-i386";
341 EnvironmentVariable::getValue("ROS_OUTPUT", m_PidFile);
342 m_PidFile += "/pid.txt";
343 m_BootCmd += " -pidfile ";
344 m_BootCmd += m_PidFile;
345 m_BootCmd += " -nographic";
346 #else
347
348 if (hasQemuNoRebootOption())
349 {
350 m_BootCmd += " -no-reboot ";
351 }
352 #endif
353 return true;
354 }
355 //----------------------------------------------------------------------------------------
356 bool RosBootTest::extractPipeFromBootCmd()
357 {
358 string::size_type pos = m_BootCmd.find("-serial pipe:");
359 if (pos == string::npos)
360 {
361 /* no debug options provided */
362 cerr << "Error: provided boot cmd does not specify a pipe debugging port" << endl;
363 return false;
364 }
365
366 string pipe = m_BootCmd.substr(pos + 13, m_BootCmd.size() - pos - 13);
367 pos = pipe.find(" ");
368 if (pos != string::npos)
369 {
370 pipe = pipe.substr(0, pos);
371 }
372 #ifdef __LINUX__
373 m_Src = pipe;
374 #else
375 m_Src = "\\\\.\\pipe\\" + pipe.substr(0, pos);
376 #endif
377 m_DebugPort = "pipe";
378 return true;
379 }
380 //----------------------------------------------------------------------------------------
381 bool RosBootTest::configureHDDImage()
382 {
383 //cout << "configureHDDImage m_HDDImage " << m_HDDImage.length() << " m_CDImage " << m_CDImage.length() << " m_BootCmd: " << m_BootCmd.length() << endl;
384 if (m_HDDImage.length())
385 {
386 /* check if ROS_HDD_IMAGE points to hdd image */
387 if (!isFileExisting(m_HDDImage))
388 {
389 if (!m_CDImage.length ())
390 {
391 cerr << "Error: HDD image is not existing and CDROM image not provided" << endl;
392 return false;
393 }
394 /* create it */
395 return createHDDImage(m_HDDImage);
396 }
397 return true;
398 }
399 else if (!m_BootCmd.length ())
400 {
401 /* no hdd image provided
402 * but also no override by
403 * ROS_BOOT_CMD
404 */
405 if (!m_CDImage.length ())
406 {
407 cerr << "Error: no HDD and CDROM image provided" << endl;
408 return false;
409 }
410
411 getDefaultHDDImage(m_HDDImage);
412 if (isFileExisting(m_HDDImage))
413 {
414 cerr << "Falling back to default hdd image " << m_HDDImage << endl;
415 return true;
416 }
417 return createHDDImage(m_HDDImage);
418 }
419 /*
420 * verify the provided ROS_BOOT_CMD for hdd image
421 *
422 */
423
424 bool hdaboot = false;
425 string::size_type pos = m_BootCmd.find ("-boot c");
426 if (pos != string::npos)
427 {
428 hdaboot = true;
429 }
430
431 pos = m_BootCmd.find("-hda ");
432 if (pos != string::npos)
433 {
434 string hdd = m_BootCmd.substr(pos + 5, m_BootCmd.length() - pos - 5);
435 if (!hdd.length ())
436 {
437 cerr << "Error: ROS_BOOT_CMD misses value of -hda option" << endl;
438 return false;
439 }
440 pos = m_BootCmd.find(" ");
441 if (pos != string::npos)
442 {
443 /// FIXME
444 /// sysreg assumes that the hdd image filename has no spaces
445 ///
446 hdd = hdd.substr(0, pos);
447 }
448 if (!isFileExisting(hdd))
449 {
450 if (hdaboot)
451 {
452 cerr << "Error: ROS_BOOT_CMD specifies booting from hda but no valid hdd image " << hdd << " provided" << endl;
453 return false;
454 }
455
456 /* the file does not exist create it */
457 return createHDDImage(hdd);
458 }
459 return true;
460 }
461
462 return false;
463 }
464 //----------------------------------------------------------------------------------------
465 bool RosBootTest::configureCDImage()
466 {
467 if (!m_BootCmd.length ())
468 {
469 if (m_CDImage.length())
470 {
471 /* we have a cd image lets check if its valid */
472 if (isFileExisting(m_CDImage))
473 {
474 cerr << "Using CDROM image " << m_CDImage << endl;
475 return true;
476 }
477 }
478 if (isFileExisting("ReactOS-RegTest.iso"))
479 {
480 m_CDImage = "ReactOS-RegTest.iso";
481 cerr << "Falling back to default CDROM image " << m_CDImage << endl;
482 return true;
483 }
484 cerr << "No CDROM image found, boot device is HDD" << endl;
485 m_CDImage = "";
486 return true;
487 }
488
489 string::size_type pos = m_BootCmd.find("-boot ");
490 if (pos == string::npos)
491 {
492 /* ROS_BOOT_CMD must provide a boot parameter*/
493 cerr << "Error: ROS_BOOT_CMD misses boot parameter" << endl;
494 return false;
495 }
496
497 string rest = m_BootCmd.substr(pos + 6, m_BootCmd.length() - pos - 6);
498 if (rest.length() < 1)
499 {
500 /* boot parameter misses option where to boot from */
501 cerr << "Error: ROS_BOOT_CMD misses boot parameter" << endl;
502 return false;
503 }
504 if (rest[0] != 'c' && rest[0] != 'd')
505 {
506 cerr << "Error: ROS_BOOT_CMD has invalid boot parameter" << endl;
507 return false;
508 }
509
510 if (rest[0] == 'c')
511 {
512 /* ROS_BOOT_CMD boots from hdd */
513 return true;
514 }
515
516 pos = m_BootCmd.find("-cdrom ");
517 if (pos == string::npos)
518 {
519 cerr << "Error: ROS_BOOT_CMD misses cdrom parameter" << endl;
520 return false;
521 }
522 rest = m_BootCmd.substr(pos + 7, m_BootCmd.length() - pos - 7);
523 if (!rest.length())
524 {
525 cerr << "Error: ROS_BOOT_CMD misses cdrom parameter" << endl;
526 return false;
527 }
528 pos = rest.find(" ");
529 if (pos != string::npos)
530 {
531 rest = rest.substr(0, pos);
532 }
533
534 if (!isFileExisting(rest))
535 {
536 cerr << "Error: cdrom image " << rest << " does not exist" << endl;
537 return false;
538 }
539 else
540 {
541 m_CDImage = rest;
542 return true;
543 }
544 }
545 //----------------------------------------------------------------------------------------
546 bool RosBootTest::configureQemu()
547 {
548 if (!isQemuPathValid())
549 {
550 cerr << "Error: the path to qemu is not valid" << endl;
551 return false;
552 }
553
554 if (!configureCDImage())
555 {
556 cerr << "Error: failed to set a valid cdrom configuration" << endl;
557 return false;
558 }
559
560 if (!configureHDDImage())
561 {
562 cerr << "Error: failed to set a valid hdd configuration" << endl;
563 return false;
564 }
565
566 if (m_BootCmd.length())
567 {
568 if (!extractPipeFromBootCmd())
569 {
570 return false;
571 }
572 }
573 else
574 {
575 if (!createBootCmd())
576 {
577 return false;
578 }
579 }
580 #ifdef __LINUX__
581 if (mkfifo(m_Src.c_str(), 400))
582 {
583 /*
584 if (errno != EEXIST)
585 {
586 cerr <<"Error: mkfifo failed with " << errno << endl;
587 }
588 */
589 return false;
590 }
591
592 #endif
593 if (m_PidFile.length () && isFileExisting(m_PidFile))
594 {
595 cerr << "Deleting pid file " << m_PidFile << endl;
596 remove(m_PidFile.c_str ());
597 }
598
599 cerr << "Opening Data Source:" << m_BootCmd << endl;
600 m_DataSource = new NamedPipeReader();
601 if (!executeBootCmd())
602 {
603
604 cerr << "Error: failed to launch emulator with: " << m_BootCmd << endl;
605 return false;
606 }
607
608 return true;
609 }
610
611 //---------------------------------------------------------------------------------------
612 bool RosBootTest::xenGetCaps()
613 {
614 FILE *fp;
615 int ch, i;
616 char buffer[2048];
617
618 fp = popen("xm info", "r");
619 if (!fp)
620 {
621 cerr << "Error getting Xen caps." << endl;
622 return false;
623 }
624 for (i=0;(i<2049)&&(feof(fp) == 0 && ((ch = fgetc(fp)) != -1)); i++)
625 {
626 buffer[i] = (char) ch;
627 }
628 buffer[i] = '\0';
629 pclose(fp);
630
631 if (strstr(buffer, "hvm") == 0)
632 {
633 cerr << "No hvm support detected!" << endl;
634 return false;
635 }
636 else
637 {
638 return true;
639 }
640
641 }
642
643 //---------------------------------------------------------------------------------------
644 bool RosBootTest::configureXen(ConfigParser &conf_parser)
645 {
646 if (!xenGetCaps())
647 {
648 return false;
649 }
650
651 if (!isFileExisting(m_XenConfig))
652 {
653 cerr << "Xen configuration file missing" << endl;
654 return false;
655 }
656 m_Src = "xm console ";
657 string xen_name = "reactos";
658 conf_parser.getStringValue(RosBootTest::XEN_CONFIG_NAME, xen_name);
659 m_Src += xen_name;
660
661 m_DataSource = new PipeReader();
662 m_BootCmd = m_EmuPath + "/xm create " + m_XenConfig;
663 if (!executeBootCmd())
664 return false;
665
666 return true;
667 }
668 //---------------------------------------------------------------------------------------
669 bool RosBootTest::configureVmWare()
670 {
671 cerr << "VmWare is currently not yet supported" << endl;
672 return false;
673 }
674 //---------------------------------------------------------------------------------------
675 bool RosBootTest::readConfigurationValues(ConfigParser &conf_parser)
676 {
677
678 if (!conf_parser.getStringValue(RosBootTest::ROS_EMU_TYPE, m_EmuType))
679 {
680 cerr << "Error: ROS_EMU_TYPE is not set" << endl;
681 return false;
682 }
683
684 if (m_EmuType == EMU_TYPE_XEN)
685 {
686 if (!conf_parser.getStringValue(RosBootTest::XEN_CONFIG_FILE, m_XenConfig))
687 {
688 cerr << "Error: XEN_CONFIG_FILE is not set" << endl;
689 return false;
690 }
691 }
692 if (!conf_parser.getStringValue(RosBootTest::ROS_EMU_PATH, m_EmuPath))
693 {
694 cerr << "Error: ROS_EMU_PATH_[LIN/WIN] is not set" << endl;
695 return false;
696 }
697 if (!m_HDDImage.length())
698 {
699 /* only read image once */
700 conf_parser.getStringValue (RosBootTest::ROS_HDD_IMAGE, m_HDDImage);
701 }
702 if (!m_CDImage.length())
703 {
704 /* only read cdimage once */
705 conf_parser.getStringValue (RosBootTest::ROS_CD_IMAGE, m_CDImage);
706 }
707 /* reset boot cmd */
708 m_BootCmd = "";
709
710
711 conf_parser.getIntValue (RosBootTest::ROS_MAX_TIME, m_MaxTime);
712 conf_parser.getStringValue (RosBootTest::ROS_LOG_FILE, m_DebugFile);
713 conf_parser.getStringValue (RosBootTest::ROS_SYM_DIR, m_SymDir);
714 conf_parser.getIntValue (RosBootTest::ROS_DELAY_READ, m_DelayRead);
715 conf_parser.getStringValue (RosBootTest::ROS_SYSREG_CHECKPOINT, m_Checkpoint);
716 conf_parser.getStringValue (RosBootTest::ROS_CRITICAL_IMAGE, m_CriticalImage);
717 conf_parser.getStringValue (RosBootTest::ROS_EMU_KILL, m_KillEmulator);
718 conf_parser.getStringValue (RosBootTest::ROS_EMU_MEM, m_MaxMem);
719 conf_parser.getStringValue (RosBootTest::ROS_BOOT_CMD, m_BootCmd);
720
721 return true;
722 }
723 //---------------------------------------------------------------------------------------
724 void RosBootTest::cleanup(ConfigParser &conf_parser)
725 {
726 m_DataSource->closeSource();
727 OsSupport::delayExecution(3);
728
729 if (m_EmuType == EMU_TYPE_XEN)
730 {
731 string xen_name = "reactos";
732 conf_parser.getStringValue(RosBootTest::XEN_CONFIG_NAME, xen_name);
733 string cmd = "xm destroy " + xen_name;
734 system(cmd.c_str ());
735 }
736 else
737 {
738 if (m_Pid)
739 {
740 OsSupport::terminateProcess (m_Pid, 0);
741 }
742 }
743 delete m_DataSource;
744 m_DataSource = NULL;
745
746 if (m_PidFile.length ())
747 {
748 remove(m_PidFile.c_str ());
749 }
750 }
751
752 //---------------------------------------------------------------------------------------
753 bool RosBootTest::execute(ConfigParser &conf_parser)
754 {
755 if (!readConfigurationValues(conf_parser))
756 {
757 return false;
758 }
759
760 if (m_EmuType == EMU_TYPE_QEMU)
761 {
762 if (!configureQemu())
763 {
764 cerr << "Error: failed to configure qemu" << endl;
765 return false;
766 }
767 }
768 else if (m_EmuType == EMU_TYPE_VMWARE)
769 {
770 if (!configureVmWare())
771 {
772 cerr << "Error: failed to configure vmware" << endl;
773 return false;
774 }
775 }
776 else if (m_EmuType == EMU_TYPE_XEN)
777 {
778 if (!configureXen(conf_parser))
779 {
780 cerr << "Error: failed to configure xen" << endl;
781 return false;
782 }
783 }
784 else
785 {
786 ///
787 /// unsupported emulator
788
789 cerr << "Error: ROS_EMU_TYPE value is not supported:" << m_EmuType << "=" << EMU_TYPE_QEMU << endl;
790 return false;
791 }
792
793 if (m_DelayRead)
794 {
795 cerr << "Delaying read for " << m_DelayRead << " seconds" << endl;
796 OsSupport::delayExecution(m_DelayRead);
797 }
798
799 if (!m_DataSource->openSource(m_Src))
800 {
801 cerr << "Error: failed to open data source with " << m_Src << endl;
802 cleanup(conf_parser);
803 return false;
804 }
805 #ifdef __LINUX__
806 /*
807 * For linux systems we can only
808 * check if the emulator runs by
809 * opening pid.txt and lookthrough if
810 * it exists
811 */
812
813 if (m_EmuType != EMU_TYPE_XEN)
814 {
815 FILE * file = fopen(m_PidFile.c_str(), "r");
816 if (!file)
817 {
818 cerr << "Error: failed to launch emulator" << endl;
819 cleanup(conf_parser);
820 return false;
821 }
822 char buffer[128];
823 if (!fread(buffer, 1, sizeof(buffer), file))
824 {
825 cerr << "Error: pid file w/o pid!!! " << endl;
826 fclose(file);
827 cleanup(conf_parser);
828 return false;
829 }
830 m_Pid = atoi(buffer);
831 fclose(file);
832 }
833 #endif
834 OsSupport::cancelAlarms();
835 #ifdef __LINUX__
836 // OsSupport::setAlarm (m_MaxTime, m_Pid);
837 // OsSupport::setAlarm(m_MaxTime, getpid());
838 #else
839 OsSupport::setAlarm (m_MaxTime, m_Pid);
840 OsSupport::setAlarm(m_MaxTime, GetCurrentProcessId());
841 #endif
842
843 bool ret = analyzeDebugData();
844 cleanup(conf_parser);
845
846 return ret;
847 }
848 //---------------------------------------------------------------------------------------
849 void RosBootTest::dumpCheckpoints()
850 {
851 if (m_Checkpoints.size ())
852 {
853 cerr << "Dumping list of checkpoints: "<< endl;
854 while(!m_Checkpoints.empty ())
855 {
856 cerr << m_Checkpoints[0] << endl;
857 m_Checkpoints.erase (m_Checkpoints.begin ());
858 }
859 }
860 }
861 //---------------------------------------------------------------------------------------
862 RosBootTest::DebugState RosBootTest::checkDebugData(vector<string> & debug_data)
863 {
864 /// TBD the information needs to be written into an provided log object
865 /// which writes the info into HTML/log / sends etc ....
866
867 bool clear = true;
868 DebugState state = DebugStateContinue;
869
870 for(size_t i = 0; i < debug_data.size();i++)
871 {
872 string line = debug_data[i];
873
874 cout << line << endl;
875
876 if (line.find (RosBootTest::ROS_SYSREG_CHECKPOINT) != string::npos)
877 {
878 line.erase (0, line.find (RosBootTest::ROS_SYSREG_CHECKPOINT) +
879 RosBootTest::ROS_SYSREG_CHECKPOINT.length ());
880 if (!strncmp(line.c_str (), m_Checkpoint.c_str (), m_Checkpoint.length ()))
881 {
882 state = DebugStateCPReached;
883 break;
884 }
885 m_Checkpoints.push_back (line);
886 }
887
888
889 if (line.find ("*** Fatal System Error") != string::npos)
890 {
891 cerr << "Blue Screen of Death detected" <<endl;
892 if (m_Checkpoints.size ())
893 {
894 cerr << "dumping list of reached checkpoints:" << endl;
895 do
896 {
897 string cp = m_Checkpoints[0];
898 m_Checkpoints.erase (m_Checkpoints.begin ());
899 cerr << cp << endl;
900 }while(m_Checkpoints.size ());
901 cerr << "----------------------------------" << endl;
902 }
903 if (i + 1 < debug_data.size () )
904 {
905 cerr << "dumping rest of debug log" << endl;
906 while(i < debug_data.size ())
907 {
908 string data = debug_data[i];
909 cerr << data << endl;
910 i++;
911 }
912 cerr << "----------------------------------" << endl;
913 }
914 state = DebugStateBSODDetected;
915 break;
916 }
917 else if (line.find ("Unhandled exception") != string::npos)
918 {
919 if (m_CriticalImage == "IGNORE")
920 {
921 ///
922 /// ignoring all user-mode exceptions
923 ///
924 continue;
925 }
926
927
928 if (i + 3 >= debug_data.size ())
929 {
930 ///
931 /// missing information is cut off -> try reconstruct at next call
932 ///
933 clear = false;
934 break;
935 }
936
937 ///
938 /// extract address from next line
939 ///
940
941 string address = debug_data[i+2];
942 string::size_type pos = address.find_last_of (" ");
943 if (pos == string::npos)
944 {
945 cerr << "Error: trace is not available (corrupted debug info" << endl;
946 continue;
947 }
948
949
950 address = address.substr (pos, address.length () - 1 - pos);
951
952 ///
953 /// extract module name
954 ///
955 string modulename = debug_data[i+3];
956
957 pos = modulename.find_last_of ("\\");
958 if (pos == string::npos)
959 {
960 cerr << "Error: trace is not available (corrupted debug info" << endl;
961 continue;
962 }
963
964 string appname = modulename.substr (pos + 1, modulename.length () - pos);
965 if (m_CriticalImage.find (appname) == string::npos && m_CriticalImage.length () > 1)
966 {
967 /// the application is not in the list of
968 /// critical apps. Therefore we ignore the user-mode
969 /// exception
970
971 continue;
972 }
973
974 pos = appname.find_last_of (".");
975 if (pos == string::npos)
976 {
977 cerr << "Error: trace is not available (corrupted debug info" << endl;
978 continue;
979 }
980
981 modulename = appname.substr (0, pos);
982
983 cerr << "UM detected" <<endl;
984 state = DebugStateUMEDetected;
985
986 ///
987 /// resolve address
988 ///
989 string result;
990 result.reserve (200);
991 #if 0
992 SymbolFile::resolveAddress (modulename, address, result);
993 cerr << result << endl;
994 #endif
995 ///
996 /// TODO
997 ///
998 /// resolve frame addresses
999
1000
1001
1002 break;
1003 }
1004 }
1005
1006 if (clear && debug_data.size () > 5)
1007 {
1008 debug_data.clear ();
1009 }
1010 return state;
1011 }
1012 //---------------------------------------------------------------------------------------
1013 bool RosBootTest::analyzeDebugData()
1014 {
1015 vector<string> vect;
1016 size_t lines = 0;
1017 bool write_log;
1018 ofstream file;
1019 bool ret = true;
1020
1021 if (m_DebugFile.length ())
1022 {
1023 remove(m_DebugFile.c_str ());
1024 file.open (m_DebugFile.c_str ());
1025 }
1026
1027 write_log = file.is_open ();
1028 while(1)
1029 {
1030 size_t prev_count = vect.size ();
1031 if (!m_DataSource->readSource (vect))
1032 {
1033 continue;
1034 }
1035 if (write_log)
1036 {
1037 for (size_t i = prev_count; i < vect.size (); i++)
1038 {
1039 string & line = vect[i];
1040 file << line;
1041 }
1042 }
1043
1044 DebugState state = checkDebugData(vect);
1045 if (state == DebugStateBSODDetected || state == DebugStateUMEDetected)
1046 {
1047 ret = false;
1048 break;
1049 }
1050 else if (state == DebugStateCPReached)
1051 {
1052 break;
1053 }
1054 lines += (vect.size() -prev_count); //WTF?
1055 }
1056 if (write_log)
1057 {
1058 file.close();
1059 }
1060
1061 return ret;
1062 }
1063 } // end of namespace Sysreg_