00001
00002
00003
00004
00005
00006
00007
00008
00012 extern "C"
00013 {
00014 #include <sys/statvfs.h>
00015 }
00016
00017 #include <iostream>
00018 #include <fstream>
00019
00020 #include "zypp/base/Logger.h"
00021 #include "zypp/base/String.h"
00022
00023 #include "zypp/DiskUsageCounter.h"
00024 #include "zypp/Package.h"
00025
00026
00028 namespace zypp
00029 {
00030
00031 DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage(const ResPool &pool)
00032 {
00033 MountPointSet result = mps;
00034
00035 if (mps.empty())
00036 {
00037
00038 return result;
00039 }
00040
00041
00042 for (MountPointSet::iterator mpit = result.begin();
00043 mpit != result.end();
00044 mpit++)
00045 {
00046 mpit->pkg_size = mpit->used_size;
00047 }
00048
00049
00050 for (ResPool::byKind_iterator it = pool.byKindBegin(ResTraits<Package>::kind);
00051 it != pool.byKindEnd(ResTraits<Package>::kind);
00052 ++it)
00053 {
00054 bool inst = it->status().isToBeInstalled();
00055 bool rem = it->status().isToBeUninstalled();
00056
00057
00058
00059 if (inst || rem)
00060 {
00061 Package::constPtr pkg = boost::dynamic_pointer_cast<const Package>( it->resolvable() );
00062 DiskUsage du = pkg->diskusage();
00063 DiskUsage du_another_package;
00064 Edition edition_another_package;
00065
00066
00067 bool found_installed = false;
00068
00069 bool found_to_install = false;
00070
00071
00072 if (du.size() == 0 || inst)
00073 {
00074
00075
00076 std::string name = (*it)->name();
00077
00078 for (ResPool::byName_iterator nameit = pool.byNameBegin(name);
00079 nameit != pool.byNameEnd(name);
00080 ++nameit)
00081 {
00082
00083 if (isKind<Package>(nameit->resolvable()))
00084 {
00085
00086 Package::constPtr pkg_from_source = boost::dynamic_pointer_cast<const Package>( nameit->resolvable() );
00087
00088 if (nameit->status().isToBeInstalled())
00089 {
00090 found_to_install = true;
00091 }
00092
00093
00094 if ((*it)->edition() == (*nameit)->edition() && (*it)->arch() == (*nameit)->arch())
00095 {
00096 if (inst)
00097 {
00098 if (nameit->status().isInstalled())
00099 {
00100 found_installed = true;
00101 XXX << name << '-' << (*it)->edition() << ": found already installed package (" << (*nameit)->edition() << ")" << std::endl;
00102 }
00103 }
00104 else
00105 {
00106
00107 du = pkg_from_source->diskusage();
00108 if (du.size() > 0)
00109 {
00110 XXX << name << '-' << (*it)->edition() << ": using DiskUsage from another Package object (" << (*nameit)->edition() << ")" << std::endl;
00111 break;
00112 }
00113 }
00114 }
00115 else
00116 {
00117 if (inst && nameit->status().isInstalled())
00118 {
00119
00120 found_installed = true;
00121 XXX << name << '-' << (*it)->edition() << ": found already installed package (" << (*nameit)->edition() << ")" << std::endl;
00122 }
00123 else if (pkg_from_source->diskusage().size() > 0)
00124 {
00125
00126
00127 du_another_package = pkg_from_source->diskusage();
00128 edition_another_package = (*nameit)->edition();
00129 }
00130 }
00131 }
00132 }
00133
00134
00135 if (du.size() == 0 && du_another_package.size() > 0 && !(rem && found_to_install))
00136 {
00137 XXX << name << '-' << (*it)->edition() << ": using DU info from version " << edition_another_package << std::endl;
00138 du = du_another_package;
00139 }
00140 }
00141
00142
00143 if (du.size() > 0 && !(inst && found_installed))
00144 {
00145
00146
00147
00148 for (MountPointSet::reverse_iterator mpit = result.rbegin();
00149 mpit != result.rend();
00150 mpit++)
00151 {
00152
00153 DiskUsage::Entry entry = du.extract(mpit->dir);
00154
00155
00156 if (inst)
00157 {
00158 mpit->pkg_size += entry._size;
00159 }
00160 else
00161 {
00162 mpit->pkg_size -= entry._size;
00163 }
00164 }
00165 }
00166 }
00167 }
00168
00169 return result;
00170 }
00171
00172
00173 DiskUsageCounter::MountPointSet DiskUsageCounter::detectMountPoints(const std::string &rootdir)
00174 {
00175 DiskUsageCounter::MountPointSet ret;
00176
00177 std::ifstream procmounts( "/proc/mounts" );
00178
00179 if ( !procmounts ) {
00180 WAR << "Unable to read /proc/mounts" << std::endl;
00181 } else {
00182
00183 std::string prfx;
00184 if ( rootdir != "/" )
00185 prfx = rootdir;
00186
00187 while ( procmounts ) {
00188 std::string l = str::getline( procmounts );
00189 if ( !(procmounts.fail() || procmounts.bad()) ) {
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 std::vector<std::string> words;
00201 str::split( l, std::back_inserter(words) );
00202
00203 if ( words.size() < 3 ) {
00204 WAR << "Suspicious entry in /proc/mounts: " << l << std::endl;
00205 continue;
00206 }
00207
00208
00209
00210
00211 if ( words[0].find( '/' ) == std::string::npos ) {
00212 DBG << "Discard mount point : " << l << std::endl;
00213 continue;
00214 }
00215
00216
00217
00218
00219 std::string mp = words[1];
00220 if ( prfx.size() ) {
00221 if ( mp.compare( 0, prfx.size(), prfx ) != 0 ) {
00222
00223 DBG << "Unwanted mount point : " << l << std::endl;
00224 continue;
00225 }
00226
00227 mp.erase( 0, prfx.size() );
00228 if ( mp.empty() ) {
00229 mp = "/";
00230 } else if ( mp[0] != '/' ) {
00231
00232 DBG << "Unwanted mount point : " << l << std::endl;
00233 continue;
00234 }
00235 }
00236
00237
00238
00239
00240 if ( words[2] == "iso9660" ) {
00241 DBG << "Discard cdrom : " << l << std::endl;
00242 continue;
00243 }
00244
00245
00246
00247
00248 char * mpunwanted[] = {
00249 "/mnt", "/media", "/mounts", "/floppy", "/cdrom",
00250 "/suse", "/var/tmp", "/var/adm/mount", "/var/adm/YaST",
00251 0
00252 };
00253
00254 char ** nomp = mpunwanted;
00255 for ( ; *nomp; ++nomp ) {
00256 std::string pre( *nomp );
00257 if ( mp.compare( 0, pre.size(), pre ) == 0
00258 && ( mp.size() == pre.size() || mp[pre.size()] == '/' ) ) {
00259 break;
00260 }
00261 }
00262 if ( *nomp ) {
00263 DBG << "Filter mount point : " << l << std::endl;
00264 continue;
00265 }
00266
00267
00268
00269
00270 bool ro = false;
00271 std::vector<std::string> flags;
00272 str::split( words[3], std::back_inserter(flags), "," );
00273
00274 for ( unsigned i = 0; i < flags.size(); ++i ) {
00275 if ( flags[i] == "ro" ) {
00276 ro = true;
00277 break;
00278 }
00279 }
00280
00281
00282
00283
00284 struct statvfs sb;
00285 if ( statvfs( words[1].c_str(), &sb ) != 0 ) {
00286 WAR << "Unable to statvfs(" << words[1] << "); errno " << errno << std::endl;
00287 ret.insert( DiskUsageCounter::MountPoint( mp ) );
00288 }
00289 else
00290 {
00291 ret.insert( DiskUsageCounter::MountPoint( mp, sb.f_bsize,
00292 ((long long)sb.f_blocks)*sb.f_bsize/1024,
00293 ((long long)(sb.f_blocks - sb.f_bfree))*sb.f_bsize/1024, 0LL, ro ) );
00294 }
00295 }
00296 }
00297 }
00298
00299 return ret;
00300 }
00301
00302 }