DiskUsageCounter.cc
Go to the documentation of this file.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/Easy.h"
00021 #include "zypp/base/LogTools.h"
00022 #include "zypp/base/DtorReset.h"
00023 #include "zypp/base/String.h"
00024
00025 #include "zypp/DiskUsageCounter.h"
00026 #include "zypp/sat/Pool.h"
00027 #include "zypp/sat/detail/PoolImpl.h"
00028
00029 using std::endl;
00030
00032 namespace zypp
00033 {
00034
00036 namespace
00037 {
00038
00039 struct SatMap : private base::NonCopyable
00040 {
00041 SatMap()
00042 {
00043 ::map_init( &_installedmap, sat::Pool::instance().capacity() );
00044 }
00045
00046 void add( sat::Solvable solv_r )
00047 {
00048 MAPSET( &_installedmap, solv_r.id() );
00049 }
00050
00051 void add( const PoolItem & pi_r )
00052 { add( pi_r->satSolvable() ); }
00053
00054 void add( const ResObject::constPtr & obj_r )
00055 { add( obj_r->satSolvable() ); }
00056
00057 mutable ::Map _installedmap;
00058 };
00059
00060 DiskUsageCounter::MountPointSet calcDiskUsage( DiskUsageCounter::MountPointSet result, const SatMap & installedmap_r )
00061 {
00062 if ( result.empty() )
00063 {
00064
00065 return result;
00066 }
00067
00068 sat::Pool satpool( sat::Pool::instance() );
00069
00070
00071 static const ::DUChanges _initdu = { 0, 0, 0 };
00072 std::vector< ::DUChanges> duchanges( result.size(), _initdu );
00073 {
00074 unsigned idx = 0;
00075 for_( it, result.begin(), result.end() )
00076 {
00077 duchanges[idx].path = it->dir.c_str();
00078 ++idx;
00079 }
00080 }
00081
00082
00083 ::pool_calc_duchanges( satpool.get(),
00084 &installedmap_r._installedmap,
00085 &duchanges[0],
00086 duchanges.size() );
00087
00088
00089 {
00090 unsigned idx = 0;
00091 for_( it, result.begin(), result.end() )
00092 {
00093 static const ByteCount blockAdjust( 2, ByteCount::K );
00094 it->pkg_size = it->used_size
00095 + duchanges[idx].kbytes
00096 + ( duchanges[idx].files * it->block_size / blockAdjust );
00097 ++idx;
00098 }
00099 }
00100
00101 return result;
00102 }
00103
00105 }
00107
00108 DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( const ResPool & pool_r )
00109 {
00110 SatMap installedmap;
00111
00112
00113 for_( it, pool_r.begin(), pool_r.end() )
00114 {
00115 if ( it->status().isInstalled() != it->status().transacts() )
00116 {
00117 installedmap.add( *it );
00118 }
00119 }
00120 return calcDiskUsage( mps, installedmap );
00121 }
00122
00123 DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( sat::Solvable solv_r )
00124 {
00125 SatMap installedmap;
00126 installedmap.add( solv_r );
00127
00128
00129 DtorReset tmp( sat::Pool::instance().get()->installed );
00130 sat::Pool::instance().get()->installed = nullptr;
00131
00132 return calcDiskUsage( mps, installedmap );
00133 }
00134
00135 DiskUsageCounter::MountPointSet DiskUsageCounter::detectMountPoints(const std::string &rootdir)
00136 {
00137 DiskUsageCounter::MountPointSet ret;
00138
00139 std::ifstream procmounts( "/proc/mounts" );
00140
00141 if ( !procmounts ) {
00142 WAR << "Unable to read /proc/mounts" << std::endl;
00143 } else {
00144
00145 std::string prfx;
00146 if ( rootdir != "/" )
00147 prfx = rootdir;
00148
00149 while ( procmounts ) {
00150 std::string l = str::getline( procmounts );
00151 if ( !(procmounts.fail() || procmounts.bad()) ) {
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 std::vector<std::string> words;
00163 str::split( l, std::back_inserter(words) );
00164
00165 if ( words.size() < 3 ) {
00166 WAR << "Suspicious entry in /proc/mounts: " << l << std::endl;
00167 continue;
00168 }
00169
00170
00171
00172
00173 if ( words[0].find( '/' ) == std::string::npos ) {
00174 DBG << "Discard mount point : " << l << std::endl;
00175 continue;
00176 }
00177
00178
00179 if (words[0] == "/proc")
00180 {
00181 DBG << "Discard /proc filesystem: " << l << std::endl;
00182 continue;
00183 }
00184
00185
00186
00187
00188 std::string mp = words[1];
00189 if ( prfx.size() ) {
00190 if ( mp.compare( 0, prfx.size(), prfx ) != 0 ) {
00191
00192 DBG << "Unwanted mount point : " << l << std::endl;
00193 continue;
00194 }
00195
00196 mp.erase( 0, prfx.size() );
00197 if ( mp.empty() ) {
00198 mp = "/";
00199 } else if ( mp[0] != '/' ) {
00200
00201 DBG << "Unwanted mount point : " << l << std::endl;
00202 continue;
00203 }
00204 }
00205
00206
00207
00208
00209 if ( words[2] == "iso9660" ) {
00210 DBG << "Discard cdrom : " << l << std::endl;
00211 continue;
00212 }
00213
00214 if ( words[2] == "vfat" || words[2] == "fat" || words[2] == "ntfs" || words[2] == "ntfs-3g")
00215 {
00216 MIL << words[1] << " contains ignored fs (" << words[2] << ')' << std::endl;
00217 continue;
00218 }
00219
00220
00221
00222
00223 const char * mpunwanted[] = {
00224 "/mnt", "/media", "/mounts", "/floppy", "/cdrom",
00225 "/suse", "/var/tmp", "/var/adm/mount", "/var/adm/YaST",
00226 0
00227 };
00228
00229 const char ** nomp = mpunwanted;
00230 for ( ; *nomp; ++nomp ) {
00231 std::string pre( *nomp );
00232 if ( mp.compare( 0, pre.size(), pre ) == 0
00233 && ( mp.size() == pre.size() || mp[pre.size()] == '/' ) ) {
00234 break;
00235 }
00236 }
00237 if ( *nomp ) {
00238 DBG << "Filter mount point : " << l << std::endl;
00239 continue;
00240 }
00241
00242
00243
00244
00245 bool ro = false;
00246 std::vector<std::string> flags;
00247 str::split( words[3], std::back_inserter(flags), "," );
00248
00249 for ( unsigned i = 0; i < flags.size(); ++i ) {
00250 if ( flags[i] == "ro" ) {
00251 ro = true;
00252 break;
00253 }
00254 }
00255 if ( ro ) {
00256 DBG << "Filter ro mount point : " << l << std::endl;
00257 continue;
00258 }
00259
00260
00261
00262
00263 struct statvfs sb;
00264 if ( statvfs( words[1].c_str(), &sb ) != 0 ) {
00265 WAR << "Unable to statvfs(" << words[1] << "); errno " << errno << std::endl;
00266 ret.insert( DiskUsageCounter::MountPoint( mp ) );
00267 }
00268 else
00269 {
00270
00271
00272
00273 if ( sb.f_blocks == 0 || sb.f_bsize == 0 )
00274 {
00275 DBG << "Filter zero-sized mount point : " << l << std::endl;
00276 continue;
00277 }
00278 ret.insert( DiskUsageCounter::MountPoint( mp, sb.f_bsize,
00279 ((long long)sb.f_blocks)*sb.f_bsize/1024,
00280 ((long long)(sb.f_blocks - sb.f_bfree))*sb.f_bsize/1024, 0LL, ro ) );
00281 }
00282 }
00283 }
00284 }
00285
00286 return ret;
00287 }
00288
00289 DiskUsageCounter::MountPointSet DiskUsageCounter::justRootPartition()
00290 {
00291 DiskUsageCounter::MountPointSet ret;
00292 ret.insert( DiskUsageCounter::MountPoint() );
00293 return ret;
00294 }
00295
00296 std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPoint & obj )
00297 {
00298 str << "dir:[" << obj.dir << "] [ bs: " << obj.blockSize()
00299 << " ts: " << obj.totalSize()
00300 << " us: " << obj.usedSize()
00301 << " (+-: " << obj.commitDiff()
00302 << ")]";
00303 return str;
00304 }
00305
00307 }