1 /****************************************************************************
2 **
3 ** Copyright (C) 2009-2010 Andrey Rijov <ANDron142@yandex.ru>
4 **
5 ** This file is part of AQEMU.
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 ** Boston, MA  02110-1301, USA.
20 **
21 ****************************************************************************/
22 
23 #include <QFile>
24 #include <QSettings>
25 
26 #include "Utils.h"
27 #include "HDD_Image_Info.h"
28 
HDD_Image_Info(QObject * parent)29 HDD_Image_Info::HDD_Image_Info( QObject *parent )
30 		: QObject( parent )
31 {
32 	QEMU_IMG_Proc = new QProcess( this );
33 }
34 
Get_Disk_Info() const35 VM::Disk_Info HDD_Image_Info::Get_Disk_Info() const
36 {
37 	return Info;
38 }
39 
Update_Disk_Info(const QString & path)40 void HDD_Image_Info::Update_Disk_Info( const QString &path )
41 {
42 	Info.Image_File_Name = path;
43 
44 	if( Info.Image_File_Name.isEmpty() )
45 	{
46 		Clear_Info();
47 		return;
48 	}
49 
50 	if( QFile::exists(Info.Image_File_Name) == false )
51 	{
52 		AQWarning( "void QEMU_IMG_Thread::run()",
53                    "Image \"" + Info.Image_File_Name + "\" does not exist!" );
54 		Clear_Info();
55 		return;
56 	}
57 	else
58 	{
59 		QStringList args;
60 		args << "info" << Info.Image_File_Name;
61 
62 		QEMU_IMG_Proc = new QProcess( this );
63 		QSettings settings;
64 		QEMU_IMG_Proc->start( settings.value("QEMU-IMG_Path", "qemu-img").toString(), args );
65 
66 		connect( QEMU_IMG_Proc, SIGNAL(finished(int, QProcess::ExitStatus)),
67 				 this, SLOT(Parse_Info(int, QProcess::ExitStatus)), Qt::DirectConnection );
68 
69 		connect( QEMU_IMG_Proc, SIGNAL(error(QProcess::ProcessError)),
70 				 this, SLOT(Clear_Info()), Qt::DirectConnection );
71 	}
72 }
73 
Clear_Info()74 void HDD_Image_Info::Clear_Info()
75 {
76 	AQDebug( "void HDD_Image_Info::Clear_Info()",
77 			 "HDD Info Not Read!" );
78 
79 	VM_HDD tmp_hdd;
80 	Info.Disk_Format = "";
81 	Info.Virtual_Size = tmp_hdd.String_to_Device_Size( "0 G" );
82 	Info.Disk_Size = tmp_hdd.String_to_Device_Size( "0 G" );
83 	Info.Cluster_Size = 0;
84 
85 	emit Completed( false );
86 }
87 
Parse_Info(int exitCode,QProcess::ExitStatus exitStatus)88 void HDD_Image_Info::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )
89 {
90 
91 
92 	QByteArray info_str_ba = QEMU_IMG_Proc->readAll();
93 	QString info_str = QString( info_str_ba ); // Create QString
94 	if( info_str.isEmpty() )
95 	{
96 		AQDebug( "void HDD_Image_Info::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )",
97 				 "Data is empty." );
98 		return;
99 	}
100 
101 	QRegExp RegInfo = QRegExp( ".*image:[\\s]+([^\n\r]+).*file format:[\\s]+([\\w\\d]+).*virtual size:[\\s]+([\\d]+[.]*[\\d]*[KMG]+).*disk size:[\\s]+([\\d]+[.]*[\\d]*[KMG]+).*cluster_size:[\\s]+([\\d]+).*" );
102 
103 	bool cluster = true;
104 		if( ! RegInfo.exactMatch(info_str) )
105 	{
106 		AQWarning( "void QEMU_IMG_Thread::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )",
107 				   "QRegExp With Cluster Size Not Matched!" );
108 
109         RegInfo = QRegExp( QString(".*image:[\\s]+([^\n\r]+).*")+
110                            QString("file format:[\\s]+([\\w\\d]+).*")+
111                            QString("virtual size:[\\s]+([\\d]+[.]*[\\d]*[KMG]+).*")+
112                            QString("disk size:[\\s]+([\\d]+[.]*[\\d]*[KMG]*).*") );
113 
114 		if( ! RegInfo.exactMatch(info_str) )
115 		{
116 			AQError( "void QEMU_IMG_Thread::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )",
117 					 "QRegExp Without Cluster Size Not Matched! Image: " + Info.Image_File_Name + "\nData: " + info_str );
118 			Clear_Info();
119 			return;
120 		}
121 		else
122 		{
123 			cluster = false;
124 		}
125 	}
126 
127 	QStringList info_lines = RegInfo.capturedTexts();
128 
129 	if( cluster && info_lines.count() != 6 )
130 	{
131 		AQError( "void QEMU_IMG_Thread::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )",
132 				 "info_str.count() != 6" );
133 		Clear_Info();
134 		return;
135 	}
136 	else if( ! cluster && info_lines.count() != 5 )
137 	{
138 		AQError( "void QEMU_IMG_Thread::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )",
139 				 "info_str.count() != 5" );
140 		Clear_Info();
141 		return;
142 	}
143 
144 	if( info_lines[1] != Info.Image_File_Name )
145 	{
146 		AQWarning( "void QEMU_IMG_Thread::Parse_Info( int exitCode, QProcess::ExitStatus exitStatus )",
147 				   QString("info_lines[1] != Image_File_Name\nDetails:\n[[%1]]\n[[%2]]").arg(info_lines[1]).arg(Info.Image_File_Name) );
148 	}
149 
150 	Info.Disk_Format = info_lines[ 2 ];
151 	VM_HDD tmp_hdd;
152 	Info.Virtual_Size = tmp_hdd.String_to_Device_Size( info_lines[3] );
153 	Info.Disk_Size = tmp_hdd.String_to_Device_Size( info_lines[4] );
154 	if( cluster ) Info.Cluster_Size = info_lines[ 5 ].toInt();
155 	else Info.Cluster_Size = 0;
156 
157 	emit Completed( true );
158 }
159