PageRenderTime 42ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_disk.php

#
PHP | 373 lines | 296 code | 49 blank | 28 comment | 88 complexity | 186078f430449d5d6c9d22aaaa759891 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /*
  3. Phoronix Test Suite
  4. URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
  5. Copyright (C) 2008 - 2012, Phoronix Media
  6. Copyright (C) 2008 - 2012, Michael Larabel
  7. phodevi_disk.php: The PTS Device Interface object for the system disk(s)
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 3 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License$mounts[1]
  17. along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. class phodevi_disk extends phodevi_device_interface
  20. {
  21. public static function read_property($identifier)
  22. {
  23. switch($identifier)
  24. {
  25. case 'identifier':
  26. $property = new phodevi_device_property('hdd_string', phodevi::smart_caching);
  27. break;
  28. case 'scheduler':
  29. $property = new phodevi_device_property('hdd_scheduler', phodevi::no_caching);
  30. break;
  31. case 'mount-options':
  32. $property = new phodevi_device_property('proc_mount_options', phodevi::no_caching);
  33. break;
  34. }
  35. return $property;
  36. }
  37. public static function device_notes()
  38. {
  39. $notes = array();
  40. if(($disk_scheduler = phodevi::read_property('disk', 'scheduler')) != null)
  41. {
  42. array_push($notes, 'Disk Scheduler: ' . $disk_scheduler);
  43. }
  44. return $notes;
  45. }
  46. public static function proc_mount_options($mount_point = null, $mounts = null)
  47. {
  48. $mount_options = false;
  49. if($mount_point == null && PTS_IS_CLIENT)
  50. {
  51. $mount_point = pts_client::test_install_root_path();
  52. }
  53. if($mounts == null && is_readable('/proc/mounts'))
  54. {
  55. $mounts = file_get_contents('/proc/mounts');
  56. }
  57. do
  58. {
  59. $mount_point = dirname($mount_point);
  60. }
  61. while(($p = strrpos($mounts, ' ' . $mount_point . ' ')) === false && $mount_point != null && $mount_point != '/');
  62. if($p)
  63. {
  64. if(($x = strrpos($mounts, PHP_EOL, (0 - strlen($mounts) + $p))) !== false)
  65. {
  66. $mounts = trim(substr($mounts, $x));
  67. }
  68. if(($x = strpos($mounts, PHP_EOL)) !== false)
  69. {
  70. $mounts = substr($mounts, 0, $x);
  71. }
  72. $mounts = explode(' ', $mounts);
  73. if(isset($mounts[4]) && $mounts[1] == $mount_point && substr($mounts[0], 0, 4) == '/dev')
  74. {
  75. // Sort mount options alphabetically so it's easier to look at...
  76. $mounts[3] = explode(',', $mounts[3]);
  77. sort($mounts[3]);
  78. $mounts[3] = implode(',', $mounts[3]);
  79. $mount_options = array(
  80. 'device' => $mounts[0],
  81. 'mount-point' => $mounts[1],
  82. 'file-system' => $mounts[2],
  83. 'mount-options' => $mounts[3]
  84. );
  85. }
  86. }
  87. return $mount_options;
  88. }
  89. public static function is_genuine($disk)
  90. {
  91. return strpos($disk, ' ') > 1 && !pts_strings::has_in_istring($disk, array('VBOX', 'QEMU', 'Virtual'));
  92. // pts_strings::string_contains($mobo, pts_strings::CHAR_NUMERIC);
  93. }
  94. public static function hdd_string()
  95. {
  96. $disks = array();
  97. if(phodevi::is_macosx())
  98. {
  99. // TODO: Support reading non-SATA drives and more than one drive
  100. $capacity = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'Capacity');
  101. $model = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'Model');
  102. if(($cut = strpos($capacity, ' (')) !== false)
  103. {
  104. $capacity = substr($capacity, 0, $cut);
  105. }
  106. if(($cut = strpos($capacity, ' ')) !== false)
  107. {
  108. if(is_numeric(substr($capacity, 0, $cut)))
  109. {
  110. $capacity = floor(substr($capacity, 0, $cut)) . substr($capacity, $cut);
  111. }
  112. }
  113. $capacity = str_replace(' GB', 'GB', $capacity);
  114. if(!empty($capacity) && !empty($model))
  115. {
  116. $disks = array($capacity . ' ' . $model);
  117. }
  118. }
  119. else if(phodevi::is_bsd())
  120. {
  121. $i = 0;
  122. do
  123. {
  124. $disk = phodevi_bsd_parser::read_sysctl('dev.ad.' . $i . '.%desc');
  125. if($disk != false)
  126. {
  127. array_push($disks, $disk);
  128. }
  129. $i++;
  130. }
  131. while(($disk != false || $i < 9) && $i < 128);
  132. // On some systems, the first drive seems to be at dev.ad.8 rather than starting at dev.ad.0
  133. if(empty($disks) && pts_client::executable_in_path('camcontrol'))
  134. {
  135. $camcontrol = trim(shell_exec('camcontrol devlist 2>&1'));
  136. foreach(explode(PHP_EOL, $camcontrol) as $line)
  137. {
  138. if(substr($line, 0, 1) == '<' && ($model_end = strpos($line, '>')) !== false)
  139. {
  140. $disk = self::prepend_disk_vendor(substr($line, 1, ($model_end - 1)));
  141. array_push($disks, $disk);
  142. }
  143. }
  144. }
  145. }
  146. else if(phodevi::is_solaris())
  147. {
  148. if(is_executable('/usr/ddu/bin/i386/hd_detect'))
  149. {
  150. $hd_detect = explode(PHP_EOL, trim(shell_exec('/usr/ddu/bin/i386/hd_detect -l 2>&1')));
  151. foreach($hd_detect as $hd_line)
  152. {
  153. if(isset($hd_line) && ($hd_pos = strpos($hd_line, ':/')) != false)
  154. {
  155. $disk = trim(substr($hd_line, 0, $hd_pos));
  156. $disk = self::prepend_disk_vendor($disk);
  157. if($disk != 'blkdev')
  158. {
  159. array_push($disks, $disk);
  160. }
  161. }
  162. }
  163. }
  164. }
  165. else if(phodevi::is_linux())
  166. {
  167. $disks_formatted = array();
  168. $disks = array();
  169. foreach(pts_file_io::glob('/sys/block/sd*') as $sdx)
  170. {
  171. if(is_file($sdx . '/device/model') && is_file($sdx . '/size'))
  172. {
  173. $disk_size = pts_file_io::file_get_contents($sdx . '/size');
  174. $disk_model = pts_file_io::file_get_contents($sdx . '/device/model');
  175. $disk_removable = pts_file_io::file_get_contents($sdx . '/removable');
  176. if($disk_removable == '1')
  177. {
  178. // Don't count removable disks
  179. continue;
  180. }
  181. $disk_size = round($disk_size * 512 / 1000000000) . 'GB';
  182. $disk_model = self::prepend_disk_vendor($disk_model);
  183. if(strpos($disk_model, $disk_size . ' ') === false && strpos($disk_model, ' ' . $disk_size) === false && $disk_size != '1GB')
  184. {
  185. $disk_model = $disk_size . ' ' . $disk_model;
  186. }
  187. if($disk_size > 0)
  188. {
  189. array_push($disks_formatted, $disk_model);
  190. }
  191. }
  192. }
  193. for($i = 0; $i < count($disks_formatted); $i++)
  194. {
  195. if(!empty($disks_formatted[$i]))
  196. {
  197. $times_found = 1;
  198. for($j = ($i + 1); $j < count($disks_formatted); $j++)
  199. {
  200. if($disks_formatted[$i] == $disks_formatted[$j])
  201. {
  202. $times_found++;
  203. $disks_formatted[$j] = '';
  204. }
  205. }
  206. $disk = ($times_found > 1 ? $times_found . ' x ' : null) . $disks_formatted[$i];
  207. array_push($disks, $disk);
  208. }
  209. }
  210. }
  211. if(is_file('/sys/class/block/mmcblk0/device/name'))
  212. {
  213. $disk_name = pts_file_io::file_get_contents('/sys/class/block/mmcblk0/device/name');
  214. $disk_size = pts_file_io::file_get_contents('/sys/class/block/mmcblk0/size');
  215. array_push($disks, round($disk_size * 512 / 1000000000) . 'GB ' . $disk_name);
  216. }
  217. if(count($disks) == 0)
  218. {
  219. $root_disk_size = ceil(disk_total_space('/') / 1073741824);
  220. $pts_disk_size = ceil(disk_total_space(pts_client::test_install_root_path()) / 1073741824);
  221. if($pts_disk_size > $root_disk_size)
  222. {
  223. $root_disk_size = $pts_disk_size;
  224. }
  225. if($root_disk_size > 1)
  226. {
  227. $disks = $root_disk_size . 'GB';
  228. }
  229. else
  230. {
  231. $disks = null;
  232. }
  233. }
  234. else
  235. {
  236. $disks = implode(' + ', $disks);
  237. }
  238. return $disks;
  239. }
  240. protected static function prepend_disk_vendor($disk_model)
  241. {
  242. if(isset($disk_model[4]))
  243. {
  244. $disk_manufacturer = null;
  245. $third_char = substr($disk_model, 2, 1);
  246. switch(substr($disk_model, 0, 2))
  247. {
  248. case 'WD':
  249. $disk_manufacturer = 'Western Digital';
  250. if(substr($disk_model, 0, 4) == 'WDC ')
  251. {
  252. $disk_model = substr($disk_model, 4);
  253. }
  254. break;
  255. case 'MK':
  256. $disk_manufacturer = 'Toshiba';
  257. break;
  258. case 'HD':
  259. if($third_char == 'T')
  260. {
  261. $disk_manufacturer = 'Hitachi';
  262. }
  263. break;
  264. case 'HT':
  265. $disk_manufacturer = 'Hitachi';
  266. break;
  267. case 'HM':
  268. case 'HN':
  269. // HM and HN appear to be Samsung series
  270. $disk_manufacturer = 'Samsung';
  271. break;
  272. case 'ST':
  273. if($third_char == 'T')
  274. {
  275. $disk_manufacturer = 'Super Talent';
  276. }
  277. else if($third_char != 'E')
  278. {
  279. $disk_manufacturer = 'Seagate';
  280. }
  281. break;
  282. }
  283. if($disk_manufacturer != null && strpos($disk_model, $disk_manufacturer) === false)
  284. {
  285. $disk_model = $disk_manufacturer . ' ' . $disk_model;
  286. }
  287. // OCZ SSDs aren't spaced
  288. $disk_model = str_replace('OCZ-', 'OCZ ', $disk_model);
  289. }
  290. return $disk_model;
  291. }
  292. public static function hdd_scheduler()
  293. {
  294. $scheduler = null;
  295. $device = self::proc_mount_options();
  296. $device = basename($device['device']);
  297. if(is_readable('/sys/block/' . ($d = pts_strings::keep_in_string($device, pts_strings::CHAR_LETTER)) . '/queue/scheduler'))
  298. {
  299. $scheduler = '/sys/block/' . $d . '/queue/scheduler';
  300. }
  301. else if(is_link(($device = '/dev/disk/by-uuid/' . $device)))
  302. {
  303. // Go from the disk UUID to the device
  304. $device = pts_strings::keep_in_string(basename(readlink($device)), pts_strings::CHAR_LETTER);
  305. if(is_readable('/sys/block/' . $device . '/queue/scheduler'))
  306. {
  307. $scheduler = '/sys/block/' . $device . '/queue/scheduler';
  308. }
  309. }
  310. if($scheduler)
  311. {
  312. $scheduler = pts_file_io::file_get_contents($scheduler);
  313. if(($s = strpos($scheduler, '[')) !== false && ($e = strpos($scheduler, ']', $s)) !== false)
  314. {
  315. $scheduler = strtoupper(substr($scheduler, ($s + 1), ($e - $s - 1)));
  316. }
  317. }
  318. return $scheduler;
  319. }
  320. }
  321. ?>