LCOV - code coverage report
Current view: top level - lib - utilities.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 14 15 93.3 %
Date: 2015-09-30 14:09:30 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /**
       2             : * This file is part of rmlint.
       3             : *
       4             : *  rmlint is free software: you can redistribute it and/or modify
       5             : *  it under the terms of the GNU General Public License as published by
       6             : *  the Free Software Foundation, either version 3 of the License, or
       7             : *  (at your option) any later version.
       8             : *
       9             : *  rmlint is distributed in the hope that it will be useful,
      10             : *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : *  GNU General Public License for more details.
      13             : *
      14             : *  You should have received a copy of the GNU General Public License
      15             : *  along with rmlint.  If not, see <http://www.gnu.org/licenses/>.
      16             : *
      17             : * Authors:
      18             : *
      19             : *  - Christopher <sahib> Pahl 2010-2015 (https://github.com/sahib)
      20             : *  - Daniel <SeeSpotRun> T.   2014-2015 (https://github.com/SeeSpotRun)
      21             : *
      22             : * Hosted on http://github.com/sahib/rmlint
      23             : *
      24             : */
      25             : 
      26             : #ifndef RM_UTILITIES_H_INCLUDE
      27             : #define RM_UTILITIES_H_INCLUDE
      28             : 
      29             : #include <glib.h>
      30             : #include <stdbool.h>
      31             : 
      32             : #include <time.h>
      33             : #include <unistd.h>
      34             : #include <sys/stat.h>
      35             : #include <fcntl.h>
      36             : #include <sys/uio.h>
      37             : 
      38             : /* Pat(h)tricia Trie implementation */
      39             : #include "pathtricia.h"
      40             : 
      41             : #if HAVE_STAT64 && !RM_IS_APPLE
      42             : typedef struct stat64 RmStat;
      43             : #else
      44             : typedef struct stat RmStat;
      45             : #endif
      46             : 
      47             : ////////////////////////////////////
      48             : //       SYSCALL WRAPPERS         //
      49             : ////////////////////////////////////
      50             : 
      51     3016155 : static inline int rm_sys_stat(const char *path, RmStat *buf) {
      52             : #if HAVE_STAT64 && !RM_IS_APPLE
      53     3016155 :     return stat64(path, buf);
      54             : #else
      55             :     return stat(path, buf);
      56             : #endif
      57             : }
      58             : 
      59      101323 : static inline int rm_sys_lstat(const char *path, RmStat *buf) {
      60             : #if HAVE_STAT64 && !RM_IS_APPLE
      61      101323 :     return lstat64(path, buf);
      62             : #else
      63             :     return lstat(path, buf);
      64             : #endif
      65             : }
      66             : 
      67      338118 : static inline int rm_sys_stat_mtime_seconds(RmStat *stat) {
      68             : #if RM_IS_APPLE
      69             :     return stat->st_mtimespec.tv_sec;
      70             : #else
      71      338118 :     return stat->st_mtim.tv_sec;
      72             : #endif
      73             : }
      74             : 
      75      221718 : static inline int rm_sys_open(const char *path, int mode) {
      76             : #if HAVE_STAT64
      77             : #ifdef O_LARGEFILE
      78      221718 :     mode |= O_LARGEFILE;
      79             : #endif
      80             : #endif
      81             : 
      82      221718 :     return open(path, mode, (S_IRUSR | S_IWUSR));
      83             : }
      84             : 
      85      221724 : static inline void rm_sys_close(int fd) {
      86      221724 :     if(close(fd) == -1) {
      87           0 :         rm_log_perror("close(2) failed");
      88             :     }
      89      221724 : }
      90             : 
      91      226111 : static inline gint64 rm_sys_preadv(int fd, const struct iovec *iov, int iovcnt,
      92             :                                    RmOff offset) {
      93             : #if RM_IS_APPLE
      94             :     if(lseek(fd, offset, SEEK_SET) == -1) {
      95             :         rm_log_perror("seek in emulated preadv failed");
      96             :     }
      97             :     return readv(fd, iov, iovcnt);
      98             : #elif RM_PLATFORM_32
      99             :     if(lseek64(fd, offset, SEEK_SET) == -1) {
     100             :         rm_log_perror("seek in emulated preadv failed");
     101             :     }
     102             :     return readv(fd, iov, iovcnt);
     103             : #else
     104      226111 :     return preadv(fd, iov, iovcnt, offset);
     105             : #endif
     106             : }
     107             : 
     108             : /////////////////////////////////////
     109             : //   UID/GID VALIDITY CHECKING     //
     110             : /////////////////////////////////////
     111             : 
     112             : typedef struct RmUserList {
     113             :     GSequence *users;
     114             :     GSequence *groups;
     115             :     GMutex mutex;
     116             : } RmUserList;
     117             : 
     118             : /**
     119             :  * @brief Create a new list of users.
     120             :  */
     121             : RmUserList *rm_userlist_new(void);
     122             : 
     123             : /**
     124             :  * @brief Check if a uid and gid is contained in the list.
     125             :  *
     126             :  * @param valid_uid (out)
     127             :  * @param valid_gid (out)
     128             :  *
     129             :  * @return true if both are valid.
     130             :  */
     131             : bool rm_userlist_contains(RmUserList *list, unsigned long uid, unsigned gid,
     132             :                           bool *valid_uid, bool *valid_gid);
     133             : 
     134             : /**
     135             :  * @brief Deallocate the memory allocated by rm_userlist_new()
     136             :  */
     137             : void rm_userlist_destroy(RmUserList *list);
     138             : 
     139             : /**
     140             :  * @brief Get the name of the user running rmlint.
     141             :  */
     142             : char *rm_util_get_username(void);
     143             : 
     144             : /**
     145             :  * @brief Get the group of the user running rmlint.
     146             :  */
     147             : char *rm_util_get_groupname(void);
     148             : 
     149             : ////////////////////////////////////
     150             : //       GENERAL UTILITES         //
     151             : ////////////////////////////////////
     152             : 
     153             : #define RM_LIST_NEXT(node) ((node) ? node->next : NULL)
     154             : 
     155             : /**
     156             :  * @brief Replace {subs} with {with} in {string}
     157             :  *
     158             :  * @return a newly allocated string, g_free it.
     159             :  */
     160             : char *rm_util_strsub(const char *string, const char *subs, const char *with);
     161             : 
     162             : /**
     163             :  * @brief Check if a file has a invalid gid/uid or both.
     164             :  *
     165             :  * @return the appropiate RmLintType for the file
     166             :  */
     167             : int rm_util_uid_gid_check(RmStat *statp, RmUserList *userlist);
     168             : 
     169             : /**
     170             :  * @brief Check if a file is a binary that is not stripped.
     171             :  *
     172             :  * @path: Path to the file to be checked.
     173             :  * @statp: valid stat pointer with st_mode filled (allow-none).
     174             :  *
     175             :  * @return: if it is a binary with debug symbols.
     176             :   */
     177             : bool rm_util_is_nonstripped(const char *path, RmStat *statp);
     178             : 
     179             : /**
     180             :  * @brief Get the basename part of the file. It does not change filename.
     181             :  *
     182             :  * @return NULL on failure, the pointer after the last / on success.
     183             :  */
     184             : char *rm_util_basename(const char *filename);
     185             : 
     186             : /**
     187             :  * @brief Check if the file or any components of it are hidden.
     188             :  *
     189             :  * @return true if it is.
     190             :  */
     191             : bool rm_util_path_is_hidden(const char *path);
     192             : 
     193             : /**
     194             :  * @brief Get the depth of a path
     195             :  *
     196             :  * @param path
     197             :  *
     198             :  * @return depth of path or 0.
     199             :  */
     200             : int rm_util_path_depth(const char *path);
     201             : 
     202             : typedef gpointer (*RmNewFunc)(void);
     203             : 
     204             : /**
     205             :  * @brief A setdefault supplementary function for GHashTable.
     206             :  *
     207             :  * This is about the same as dict.setdefault in python.
     208             :  *
     209             :  * @param table the table to use
     210             :  * @param key key to lookup
     211             :  * @param default_func if the key does not exist in table, return default_func
     212             :  * and insert it into table
     213             :  *
     214             :  * @return value, which may be default_func() if key does not exist.
     215             :  */
     216             : GQueue *rm_hash_table_setdefault(GHashTable *table, gpointer key, RmNewFunc default_func);
     217             : 
     218             : /**
     219             :  * @brief Return a pointer to the extension part of the file or NULL if none.
     220             :  *
     221             :  * @return: a pointer >= basename or NULL.
     222             :  */
     223             : char *rm_util_path_extension(const char *basename);
     224             : 
     225             : /**
     226             :  * @brief Get the inode of the directory of the file specified in path.
     227             :  */
     228             : ino_t rm_util_parent_node(const char *path);
     229             : 
     230             : /*
     231             :  * @brief Takes num and converts into some human readable string. 1024 -> 1KB
     232             :  */
     233             : void rm_util_size_to_human_readable(RmOff num, char *in, gsize len);
     234             : 
     235             : /////////////////////////////////////
     236             : //    MOUNTTABLE IMPLEMENTATION    //
     237             : /////////////////////////////////////
     238             : 
     239             : typedef struct RmMountTable {
     240             :     GHashTable *part_table;
     241             :     GHashTable *disk_table;
     242             :     GHashTable *nfs_table;
     243             :     GHashTable *evilfs_table;
     244             :     GHashTable *reflinkfs_table;
     245             : } RmMountTable;
     246             : 
     247             : /**
     248             :  * @brief Allocates a new mounttable.
     249             :  * @param force_fiemap Create random fiemap data always. Useful for testing.
     250             :  *
     251             :  * @return The mounttable. Free with rm_mounts_table_destroy.
     252             :  */
     253             : RmMountTable *rm_mounts_table_new(bool force_fiemap);
     254             : 
     255             : /**
     256             :  * @brief Destroy a previously allocated mounttable.
     257             :  *
     258             :  * @param self the table to destroy.
     259             :  */
     260             : void rm_mounts_table_destroy(RmMountTable *self);
     261             : 
     262             : /**
     263             :  * @brief Check if the device is or is part of a nonrotational device.
     264             :  *
     265             :  * This operation has constant time.
     266             :  *
     267             :  * @param self the table to lookup from.
     268             :  * @param device the dev_t of a file, e.g. looked up from rm_sys_stat(2)
     269             :  *
     270             :  * @return true if it is non a nonrational device.
     271             :  */
     272             : bool rm_mounts_is_nonrotational(RmMountTable *self, dev_t device);
     273             : 
     274             : /**
     275             :  * @brief Return name of device/disk.
     276             :  *
     277             :  * This operation has constant time.
     278             :  *
     279             :  * @param self the table to lookup from.
     280             :  * @param device the dev_t of a disk
     281             :  *
     282             :  * @return pointer to disk name.
     283             :  */
     284             : char *rm_mounts_get_disk_name(RmMountTable *self, dev_t device);
     285             : 
     286             : /**
     287             :  * @brief Get the disk behind the partition.
     288             :  *
     289             :  * @param self the table to lookup from.
     290             :  * @param partition the dev_t of a partition (sda1 -> 8:1), e.g. looked up from
     291             :  *rm_sys_stat(2)
     292             :  *
     293             :  * @return the dev_t of the whole disk. (sda 8:0)
     294             :  */
     295             : dev_t rm_mounts_get_disk_id(RmMountTable *self, dev_t partition, const char *path);
     296             : 
     297             : /**
     298             :  * @brief Same as above, but calls rm_sys_stat(2) on path for you.
     299             :  */
     300             : dev_t rm_mounts_get_disk_id_by_path(RmMountTable *self, const char *path);
     301             : 
     302             : /**
     303             :  * @brief Indicates true if dev_t points to a filesystem that might confuse
     304             :  * rmlint.
     305             :  */
     306             : bool rm_mounts_is_evil(RmMountTable *self, dev_t to_check);
     307             : 
     308             : /**
     309             :  * @brief Indicates true if source and dest are on same partition, and the
     310             :  * partition supports reflink copies (cp --reflink).
     311             :  */
     312             : bool rm_mounts_can_reflink(RmMountTable *self, dev_t source, dev_t dest);
     313             : 
     314             : /////////////////////////////////
     315             : //    FIEMAP IMPLEMENATION     //
     316             : /////////////////////////////////
     317             : 
     318             : /**
     319             :  * @brief Lookup the physical offset of a file fd at any given offset.
     320             :  *
     321             :  * @return the physical offset starting from the disk.
     322             :  */
     323             : RmOff rm_offset_get_from_fd(int fd, RmOff file_offset, RmOff *file_offset_next);
     324             : 
     325             : /**
     326             :  * @brief Lookup the physical offset of a file path at any given offset.
     327             :  *
     328             :  * @return the physical offset starting from the disk.
     329             :  */
     330             : RmOff rm_offset_get_from_path(const char *path, RmOff file_offset,
     331             :                               RmOff *file_offset_next);
     332             : 
     333             : /**
     334             :  * @brief Test if two files have identical fiemaps.
     335             :  */
     336             : bool rm_offsets_match(char *path1, char *path2);
     337             : 
     338             : //////////////////////////////
     339             : //    TIMESTAMP HELPERS     //
     340             : //////////////////////////////
     341             : 
     342             : /**
     343             :  * @brief Parse a ISO8601 timestamp to a unix timestamp.
     344             :  */
     345             : time_t rm_iso8601_parse(const char *string);
     346             : 
     347             : /**
     348             :  * @brief convert a unix timestamp as iso8601 timestamp string.
     349             :  *
     350             :  * @param stamp unix timestamp
     351             :  * @param buf result buffer to hold the string.
     352             :  * @param buf_size sizeof buf.
     353             :  *
     354             :  * @return true if conversion succeeded.
     355             :  */
     356             : bool rm_iso8601_format(time_t stamp, char *buf, gsize buf_size);
     357             : 
     358             : ///////////////////////////////
     359             : //    THREADPOOL HELPERS     //
     360             : ///////////////////////////////
     361             : 
     362             : /**
     363             :  * @brief Create a new GThreadPool with default cfg.
     364             :  *
     365             :  * @param func func to execute
     366             :  * @param data user_data to pass
     367             :  * @param threads how many threads at max to use.
     368             :  *
     369             :  * @return newly allocated GThreadPool
     370             :  */
     371             : GThreadPool *rm_util_thread_pool_new(GFunc func, gpointer data, int threads);
     372             : 
     373             : /**
     374             :  * @brief Push a new job to a threadpool.
     375             :  *
     376             :  * @return true on success.
     377             :  */
     378             : bool rm_util_thread_pool_push(GThreadPool *pool, gpointer data);
     379             : 
     380             : /////////////////////////////////////
     381             : //    JSON CACHE IMPLEMENTATION    //
     382             : /////////////////////////////////////
     383             : 
     384             : /**
     385             :  * @brief Read json_path and write (path:cksum) into cksum_table.
     386             :  *
     387             :  * @param file_trie to set read cksums in.
     388             :  * @param json_path path with .json file.
     389             :  *
     390             :  * @return 0 on success.
     391             :  */
     392             : int rm_json_cache_read(RmTrie *file_trie, const char *json_path);
     393             : 
     394             : #endif /* RM_UTILITIES_H_INCLUDE*/

Generated by: LCOV version 1.11