libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 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 // partitioning is not set 00066 return result; 00067 } 00068 00069 sat::Pool satpool( sat::Pool::instance() ); 00070 00071 // init libsolv result vector with mountpoints 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 // now calc... 00084 ::pool_calc_duchanges( satpool.get(), 00085 &installedmap_r._installedmap, 00086 &duchanges[0], 00087 duchanges.size() ); 00088 00089 // and process the result 00090 { 00091 unsigned idx = 0; 00092 for_( it, result.begin(), result.end() ) 00093 { 00094 static const ByteCount blockAdjust( 2, ByteCount::K ); // (files * blocksize) / (2 * 1K) 00095 00096 it->pkg_size = it->used_size // current usage 00097 + duchanges[idx].kbytes // package data size 00098 + ( duchanges[idx].files * it->block_size / blockAdjust ); // half block per file 00099 ++idx; 00100 } 00101 } 00102 00103 return result; 00104 } 00105 00107 } // namespace 00109 00110 DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( const ResPool & pool_r ) 00111 { 00112 SatMap installedmap( sat::Pool::instance().capacity() ); 00113 // build installedmap (installed != transact) 00114 // stays installed or gets installed 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; // rootdir not / 00145 00146 while ( procmounts ) { 00147 std::string l = str::getline( procmounts ); 00148 if ( !(procmounts.fail() || procmounts.bad()) ) { 00149 // data to consume 00150 00151 // rootfs / rootfs rw 0 0 00152 // /dev/root / reiserfs rw 0 0 00153 // proc /proc proc rw 0 0 00154 // devpts /dev/pts devpts rw 0 0 00155 // /dev/hda5 /boot ext2 rw 0 0 00156 // shmfs /dev/shm shm rw 0 0 00157 // usbdevfs /proc/bus/usb usbdevfs rw 0 0 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 // Filter devices without '/' (proc,shmfs,..) 00169 // 00170 if ( words[0].find( '/' ) == std::string::npos ) { 00171 DBG << "Discard mount point : " << l << std::endl; 00172 continue; 00173 } 00174 00175 // remove /proc entry 00176 if (words[0] == "/proc") 00177 { 00178 DBG << "Discard /proc filesystem: " << l << std::endl; 00179 continue; 00180 } 00181 00182 // 00183 // Filter mountpoints not at or below _rootdir 00184 // 00185 std::string mp = words[1]; 00186 if ( prfx.size() ) { 00187 if ( mp.compare( 0, prfx.size(), prfx ) != 0 ) { 00188 // mountpoint not below rootdir 00189 DBG << "Unwanted mount point : " << l << std::endl; 00190 continue; 00191 } 00192 // strip prfx 00193 mp.erase( 0, prfx.size() ); 00194 if ( mp.empty() ) { 00195 mp = "/"; 00196 } else if ( mp[0] != '/' ) { 00197 // mountpoint not below rootdir 00198 DBG << "Unwanted mount point : " << l << std::endl; 00199 continue; 00200 } 00201 } 00202 00203 // 00204 // Filter cdrom 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 // Filter some common unwanted mountpoints 00219 // 00220 const char * mpunwanted[] = { 00221 "/mnt", "/media", "/mounts", "/floppy", "/cdrom", 00222 "/suse", "/var/tmp", "/var/adm/mount", "/var/adm/YaST", 00223 /*last*/0/*entry*/ 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 // mp has prefix pre 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 // Check whether mounted readonly 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 // statvfs (full path!) and get the data 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 // 00268 // Filter zero sized devices (bnc#769819) 00269 // 00270 if ( sb.f_blocks == 0 || sb.f_bsize == 0 ) 00271 { 00272 DBG << "Filter zero-sized mount point : " << l << std::endl; 00273 continue; 00274 } 00275 ret.insert( DiskUsageCounter::MountPoint( mp, sb.f_bsize, 00276 ((long long)sb.f_blocks)*sb.f_bsize/1024, 00277 ((long long)(sb.f_blocks - sb.f_bfree))*sb.f_bsize/1024, 0LL, ro ) ); 00278 } 00279 } 00280 } 00281 } 00282 00283 return ret; 00284 } 00285 00286 DiskUsageCounter::MountPointSet DiskUsageCounter::justRootPartition() 00287 { 00288 DiskUsageCounter::MountPointSet ret; 00289 ret.insert( DiskUsageCounter::MountPoint() ); 00290 return ret; 00291 } 00292 00293 std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPoint & obj ) 00294 { 00295 str << "dir:[" << obj.dir << "] [ bs: " << obj.blockSize() 00296 << " ts: " << obj.totalSize() 00297 << " us: " << obj.usedSize() 00298 << " (+-: " << obj.commitDiff() 00299 << ")]"; 00300 return str; 00301 } 00302 00304 } // namespace zypp