libzypp 9.41.1
|
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/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 // partitioning is not set 00065 return result; 00066 } 00067 00068 sat::Pool satpool( sat::Pool::instance() ); 00069 00070 // init satsolver result vector with mountpoints 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 // now calc... 00083 ::pool_calc_duchanges( satpool.get(), 00084 &installedmap_r._installedmap, 00085 &duchanges[0], 00086 duchanges.size() ); 00087 00088 // and process the result 00089 { 00090 unsigned idx = 0; 00091 for_( it, result.begin(), result.end() ) 00092 { 00093 static const ByteCount blockAdjust( 2, ByteCount::K ); // (files * blocksize) / (2 * 1K) 00094 it->pkg_size = it->used_size // current usage 00095 + duchanges[idx].kbytes // package data size 00096 + ( duchanges[idx].files * it->block_size / blockAdjust ); // half block per file 00097 ++idx; 00098 } 00099 } 00100 00101 return result; 00102 } 00103 00105 } // namespace 00107 00108 DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( const ResPool & pool_r ) 00109 { 00110 SatMap installedmap; 00111 // build installedmap (installed != transact) 00112 // stays installed or gets installed 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 // temp. unset @system Repo 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; // rootdir not / 00148 00149 while ( procmounts ) { 00150 std::string l = str::getline( procmounts ); 00151 if ( !(procmounts.fail() || procmounts.bad()) ) { 00152 // data to consume 00153 00154 // rootfs / rootfs rw 0 0 00155 // /dev/root / reiserfs rw 0 0 00156 // proc /proc proc rw 0 0 00157 // devpts /dev/pts devpts rw 0 0 00158 // /dev/hda5 /boot ext2 rw 0 0 00159 // shmfs /dev/shm shm rw 0 0 00160 // usbdevfs /proc/bus/usb usbdevfs rw 0 0 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 // Filter devices without '/' (proc,shmfs,..) 00172 // 00173 if ( words[0].find( '/' ) == std::string::npos ) { 00174 DBG << "Discard mount point : " << l << std::endl; 00175 continue; 00176 } 00177 00178 // remove /proc entry 00179 if (words[0] == "/proc") 00180 { 00181 DBG << "Discard /proc filesystem: " << l << std::endl; 00182 continue; 00183 } 00184 00185 // 00186 // Filter mountpoints not at or below _rootdir 00187 // 00188 std::string mp = words[1]; 00189 if ( prfx.size() ) { 00190 if ( mp.compare( 0, prfx.size(), prfx ) != 0 ) { 00191 // mountpoint not below rootdir 00192 DBG << "Unwanted mount point : " << l << std::endl; 00193 continue; 00194 } 00195 // strip prfx 00196 mp.erase( 0, prfx.size() ); 00197 if ( mp.empty() ) { 00198 mp = "/"; 00199 } else if ( mp[0] != '/' ) { 00200 // mountpoint not below rootdir 00201 DBG << "Unwanted mount point : " << l << std::endl; 00202 continue; 00203 } 00204 } 00205 00206 // 00207 // Filter cdrom 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 // Filter some common unwanted mountpoints 00222 // 00223 const char * mpunwanted[] = { 00224 "/mnt", "/media", "/mounts", "/floppy", "/cdrom", 00225 "/suse", "/var/tmp", "/var/adm/mount", "/var/adm/YaST", 00226 /*last*/0/*entry*/ 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 // mp has prefix pre 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 // Check whether mounted readonly 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 // statvfs (full path!) and get the data 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 // Filter zero sized devices (bnc#769819) 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 } // namespace zypp