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