LCOV - code coverage report
Current view: top level - libcdpfgl - files.c (source / functions) Hit Total Coverage
Test: coverage-libcdpfgl.info Lines: 118 189 62.4 %
Date: 2016-02-03 22:31:46 Functions: 12 20 60.0 %

          Line data    Source code
       1             : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
       2             : /*
       3             :  *    files.c
       4             :  *    This file is part of "Sauvegarde" project.
       5             :  *
       6             :  *    (C) Copyright 2014 - 2016 Olivier Delhomme
       7             :  *     e-mail : olivier.delhomme@free.fr
       8             :  *
       9             :  *    "Sauvegarde" is free software: you can redistribute it and/or modify
      10             :  *    it under the terms of the GNU General Public License as published by
      11             :  *    the Free Software Foundation, either version 3 of the License, or
      12             :  *    (at your option) any later version.
      13             :  *
      14             :  *    "Sauvegarde" is distributed in the hope that it will be useful,
      15             :  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :  *    GNU General Public License for more details.
      18             :  *
      19             :  *    You should have received a copy of the GNU General Public License
      20             :  *    along with "Sauvegarde".  If not, see <http://www.gnu.org/licenses/>
      21             :  */
      22             : 
      23             : /**
      24             :  * @file files.c
      25             :  * This file contains the functions to deal with files of the "Sauvegarde"
      26             :  * collection programs.
      27             :  */
      28             : 
      29             : #include "libcdpfgl.h"
      30             : 
      31             : 
      32             : /**
      33             :  * @returns a newly allocated meta_data_t * empty structure. We use 65534
      34             :  * as default uid and gid to avoid using 0 which is dedicated to a
      35             :  * priviledged user.
      36             :  */
      37      101698 : meta_data_t *new_meta_data_t(void)
      38             : {
      39      101698 :     meta_data_t *meta = NULL;
      40             : 
      41      101698 :     meta = (meta_data_t *) g_malloc(sizeof(meta_data_t));
      42             : 
      43      101698 :     if (meta != NULL)
      44             :         {
      45      101698 :             meta->file_type = 0;
      46      101698 :             meta->inode = 0;
      47      101698 :             meta->mode = 0;
      48      101698 :             meta->atime = 0;
      49      101698 :             meta->ctime = 0;
      50      101698 :             meta->mtime = 0;
      51      101698 :             meta->size = 0;
      52      101698 :             meta->owner = NULL;
      53      101698 :             meta->group = NULL;
      54      101698 :             meta->uid = 65534;  /* nfsnobody on my system ie unpriviledged user */
      55      101698 :             meta->gid = 65534;  /* nfsnobody on my system ie unpriviledged user */
      56      101698 :             meta->name = NULL;
      57      101698 :             meta->link = NULL;
      58      101698 :             meta->hash_data_list = NULL;
      59      101698 :             meta->in_cache = FALSE; /* a newly meta data is not in the local cache ! */
      60      101698 :             meta->blocksize = 16384; /* Default blocksize */
      61             :         }
      62             : 
      63      101698 :     return meta;
      64             : }
      65             : 
      66             : 
      67             : /**
      68             :  * @returns a newly allocated server_meta_data_t * empty structure.
      69             :  */
      70       49926 : server_meta_data_t *new_smeta_data_t(void)
      71             : {
      72       49926 :     server_meta_data_t *smeta = NULL;
      73             : 
      74       49926 :     smeta = (server_meta_data_t *) g_malloc(sizeof(server_meta_data_t));
      75             : 
      76       49926 :     if (smeta != NULL)
      77             :         {
      78       49926 :             smeta->hostname = NULL;
      79       49926 :             smeta->data_sent = FALSE;
      80       49926 :             smeta->meta = NULL;
      81             :         }
      82             : 
      83       49926 :     return smeta;
      84             : }
      85             : 
      86             : 
      87             : /**
      88             :  * Frees the meta_data_t * structure
      89             :  * @param meta is a meta_data_t * structure to be freed
      90             :  * @param free_link is a boolean that when set to TRUE will free
      91             :  * @returns always NULL
      92             :  */
      93      101698 : gpointer free_meta_data_t(meta_data_t *meta, gboolean free_link)
      94             : {
      95      101698 :     if (meta != NULL)
      96             :         {
      97      101698 :             free_variable(meta->owner);
      98      101698 :             free_variable(meta->group);
      99      101698 :             free_variable(meta->name);
     100             : 
     101      101698 :             if (free_link == TRUE)
     102             :                 {
     103             :                     /* meta->link should not be freed only in 'client' program */
     104       49926 :                     free_variable(meta->link);
     105             :                 }
     106             : 
     107      101698 :             g_list_free_full(meta->hash_data_list, free_hdt_struct);
     108      101698 :             free_variable(meta);
     109             :         }
     110             : 
     111      101698 :     return NULL;
     112             : }
     113             : 
     114             : 
     115             : /**
     116             :  * Frees the server_meta_data_t * structure
     117             :  * @param smeta is a meta_data_t * structure to be freed
     118             :  * @returns always NULL
     119             :  */
     120       49926 : gpointer free_smeta_data_t(server_meta_data_t *smeta)
     121             : {
     122       49926 :     if (smeta != NULL)
     123             :         {
     124       49926 :             smeta->meta = free_meta_data_t(smeta->meta, TRUE);
     125       49926 :             smeta->hostname = free_variable(smeta->hostname);
     126       49926 :             smeta = free_variable(smeta);
     127             :         }
     128             : 
     129       49926 :     return NULL;
     130             : }
     131             : 
     132             : 
     133             : /**
     134             :  * Wrapper for the g_slist_free_full function
     135             :  * the pointer to the data to be freed
     136             :  * @param the pointer to the data to be freed by free_smeta_data_t call.
     137             :  */
     138           7 : void gslist_free_smeta(gpointer data)
     139             : {
     140           7 :     free_smeta_data_t((server_meta_data_t *)data);
     141           7 : }
     142             : 
     143             : 
     144             : /**
     145             :  * Gets the filename of a  GFile
     146             :  * @param a_file : the GFile to get the filename from.
     147             :  * @returns the name of the GFile if any or "--" gchar * string that may be
     148             :  *          freed when no longer needed
     149             :  */
     150           0 : gchar *get_filename_from_gfile(GFile *a_file)
     151             : {
     152           0 :     gchar *filename = NULL;
     153             : 
     154           0 :     if (a_file != NULL)
     155             :         {
     156           0 :             filename = g_file_get_parse_name(a_file);
     157             :         }
     158             : 
     159           0 :     return filename;
     160             : }
     161             : 
     162             : 
     163             : /**
     164             :  * Returns the inode of the file fileinfo
     165             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     166             :  *                   (GFile *)
     167             :  * @param[out] meta : meta_data_t * structure that contains all meta data
     168             :  *                    for the corresponding file (populated here with
     169             :  *                    inode number.
     170             :  * @returns the inode file.
     171             :  */
     172           0 : guint64 get_inode_from_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     173             : {
     174           0 :     guint64 inode = 0;
     175             : 
     176             : 
     177           0 :     if (fileinfo != NULL && meta != NULL)
     178             :         {
     179           0 :             inode = g_file_info_get_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_UNIX_INODE);
     180             : 
     181           0 :             meta->inode = inode;
     182             :         }
     183             : 
     184           0 :     return inode;
     185             : }
     186             : 
     187             : 
     188             : /**
     189             :  * Returns the username of the owner of the file fileinfo
     190             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     191             :  *                   (GFile *)
     192             :  * @param[out] meta : meta_data_t * structure that contains all meta data
     193             :  *                    for the corresponding file (populated here with owner,
     194             :  *                    group, uid and gid.
     195             :  * @returns the "user:group uid:gid" of the file or an empty string if an
     196             :  *          error occurs
     197             :  */
     198           0 : gchar *get_username_owner_from_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     199             : {
     200           0 :     gchar *result = NULL;
     201             : 
     202           0 :     if (fileinfo != NULL && meta != NULL)
     203             :         {
     204             : 
     205             : 
     206           0 :             meta->owner = g_file_info_get_attribute_as_string(fileinfo, G_FILE_ATTRIBUTE_OWNER_USER);
     207           0 :             meta->group = g_file_info_get_attribute_as_string(fileinfo, G_FILE_ATTRIBUTE_OWNER_GROUP);
     208             : 
     209           0 :             meta->uid = g_file_info_get_attribute_uint32(fileinfo, G_FILE_ATTRIBUTE_UNIX_UID);
     210           0 :             meta->gid = g_file_info_get_attribute_uint32(fileinfo, G_FILE_ATTRIBUTE_UNIX_GID);
     211             : 
     212           0 :             result = g_strdup_printf("%s:%s %d:%d", meta->owner, meta->group, meta->uid, meta->gid);
     213             :         }
     214             :     else
     215             :         {
     216           0 :             result = g_strdup("");
     217             :         }
     218             : 
     219           0 :     return result;
     220             : }
     221             : 
     222             : 
     223             : /**
     224             :  * Returns the dates of a file
     225             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     226             :  *        (GFile *)
     227             :  * @param meta : meta_data_t * structure that contains all meta data for
     228             :  *        the corresponding file.
     229             :  * @returns "access_time changed_time modified_time" gchar *string
     230             :  */
     231           0 : gchar *get_dates_from_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     232             : {
     233           0 :     gchar *result = NULL;
     234             : 
     235           0 :     if (fileinfo != NULL && meta != NULL)
     236             :         {
     237           0 :             meta->atime = g_file_info_get_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_TIME_ACCESS);
     238           0 :             meta->ctime = g_file_info_get_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_TIME_CHANGED);
     239           0 :             meta->mtime = g_file_info_get_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_TIME_MODIFIED);
     240             : 
     241           0 :             result = g_strdup_printf("%" G_GUINT64_FORMAT " %"  G_GUINT64_FORMAT " %"  G_GUINT64_FORMAT "", meta->atime, meta->ctime, meta->mtime);
     242             :         }
     243             :     else
     244             :         {
     245           0 :             result = g_strdup("");
     246             :         }
     247             : 
     248           0 :     return result;
     249             : }
     250             : 
     251             : 
     252             : /**
     253             :  * sets the dates to a file
     254             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     255             :  *        (GFile *)
     256             :  * @param meta : meta_data_t * structure that contains all meta data for
     257             :  *        to set to the corresponding file.
     258             :  */
     259           4 : void set_dates_to_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     260             : {
     261           4 :     if (fileinfo != NULL && meta != NULL)
     262             :         {
     263           4 :             g_file_info_set_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_TIME_ACCESS, meta->atime);
     264           4 :             g_file_info_set_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_TIME_CHANGED, meta->ctime);
     265           4 :             g_file_info_set_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_TIME_MODIFIED, meta->mtime);
     266             :         }
     267           4 : }
     268             : 
     269             : 
     270             : /**
     271             :  * Get unix mode of a file
     272             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     273             :  *        (GFile *)
     274             :  * @param meta : meta_data_t * structure that contains all meta data for
     275             :  *        the corresponding file.
     276             :  * @returns a newly allocated string with file mode in decimal
     277             :  *          representation.
     278             :  */
     279           0 : gchar *get_file_mode_from_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     280             : {
     281           0 :     gchar *result = NULL;
     282             : 
     283           0 :     if (fileinfo != NULL)
     284             :         {
     285           0 :             meta->mode = g_file_info_get_attribute_uint32(fileinfo, G_FILE_ATTRIBUTE_UNIX_MODE);
     286             : 
     287           0 :             result =  g_strdup_printf("%d", meta->mode);
     288             :         }
     289             :     else
     290             :         {
     291           0 :             result = g_strdup("");
     292             :         }
     293             : 
     294           0 :     return result;
     295             : }
     296             : 
     297             : 
     298             : /**
     299             :  * Set unix mode of a file
     300             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     301             :  *        (GFile *)
     302             :  * @param meta : meta_data_t * structure that contains all meta data for
     303             :  *        the corresponding file.
     304             :  */
     305           4 : void set_file_mode_to_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     306             : {
     307           4 :     if (fileinfo != NULL && meta != NULL)
     308             :         {
     309           4 :             print_debug(_("Setting mode: %d\n"), meta->mode);
     310           4 :             g_file_info_set_attribute_uint32(fileinfo, G_FILE_ATTRIBUTE_UNIX_MODE, meta->mode);
     311             :         }
     312           4 : }
     313             : 
     314             : 
     315             : /**
     316             :  * Gets the size of a file
     317             :  * @param fileinfo : a GFileInfo pointer obtained from an opened file
     318             :  *        (GFile *)
     319             :  * @param meta : meta_data_t * structure that contains all meta data for
     320             :  *        the corresponding file.
     321             :  * @returns a newly allocated string with file size in decimal
     322             :  *          representation.
     323             :  */
     324           0 : gchar *get_file_size_from_gfile(GFileInfo *fileinfo, meta_data_t *meta)
     325             : {
     326           0 :     gchar *result = NULL;
     327             : 
     328           0 :     if (fileinfo != NULL)
     329             :         {
     330           0 :             meta->size = g_file_info_get_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_STANDARD_SIZE);
     331             : 
     332           0 :             result = g_strdup_printf("%"  G_GUINT64_FORMAT "", meta->size);
     333             :         }
     334             :     else
     335             :         {
     336           0 :             result = g_strdup("");
     337             :         }
     338             : 
     339           0 :     return result;
     340             : }
     341             : 
     342             : 
     343             : /**
     344             :  * Returns the file size from a GFile * file
     345             :  * @param file is the GFile from which we want the size.
     346             :  * @returns a guint64 that represents the file size or 0.
     347             :  */
     348           0 : guint64 get_file_size(GFile *file)
     349             : {
     350           0 :     GError *error = NULL;
     351           0 :     GFileInfo *fileinfo = NULL;
     352           0 :     guint64 size = 0;
     353             : 
     354           0 :     if (file != NULL)
     355             :         {
     356           0 :             fileinfo = g_file_query_info(file, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
     357           0 :             size = g_file_info_get_attribute_uint64(fileinfo, G_FILE_ATTRIBUTE_STANDARD_SIZE);
     358           0 :             free_object(fileinfo);
     359             :         }
     360             : 
     361           0 :     return size;
     362             : }
     363             : 
     364             : 
     365             : /**
     366             :  * Checks if a filename exists or not.
     367             :  * @param filename that we want to check.
     368             :  * @returns TRUE if filename exists and FALSE if not.
     369             :  */
     370           6 : gboolean file_exists(gchar *filename)
     371             : {
     372           6 :     GFile *file = NULL;
     373           6 :     gboolean exists = FALSE;
     374             : 
     375           6 :     if (filename != NULL)
     376             :         {
     377           6 :             file = g_file_new_for_path(filename);
     378           6 :             exists = g_file_query_exists(file, NULL);
     379           6 :             free_object(file);
     380             :         }
     381             : 
     382           6 :     return exists;
     383             : }
     384             : 
     385             : 
     386             : /**
     387             :  * Comparison function to be used when sorting filenames. First filenames
     388             :  * are compared and when an equality is found then the modified time is
     389             :  * compared (as a second sorting criteria)
     390             :  * @param a server_meta_data_t * representing a file 'a'
     391             :  * @param b server_meta_data_t * representing a file 'b' to be compared
     392             :  *          with 'a'
     393             :  * @returns a negative integer if the a comes before b, 0 if they are
     394             :  *          equal, or a positive integer if the a comes after b.
     395             :  */
     396         709 : gint compare_filenames(gconstpointer a, gconstpointer b)
     397             : {
     398         709 :     gchar *key_a = NULL;
     399         709 :     gchar *key_b = NULL;
     400         709 :     gint value = 0;
     401         709 :     server_meta_data_t *sa = (server_meta_data_t *) a;
     402         709 :     server_meta_data_t *sb = (server_meta_data_t *) b;
     403             : 
     404             : 
     405         709 :     key_a = g_utf8_collate_key_for_filename(sa->meta->name, -1);
     406         709 :     key_b = g_utf8_collate_key_for_filename(sb->meta->name, -1);
     407             : 
     408         709 :     value = strcmp(key_a, key_b);
     409             : 
     410         709 :     if (value == 0)
     411             :         { /* second sorting criteria : modification time */
     412          14 :             if (sa->meta->mtime < sb->meta->mtime)
     413             :                 {
     414             :                     value = -1;
     415             :                 }
     416          14 :             else if (sa->meta->mtime > sb->meta->mtime)
     417             :                 {
     418             :                     value = 1;
     419             :                 }
     420             :             else
     421             :                 {
     422           0 :                     value = 0;
     423             :                 }
     424             :         }
     425             : 
     426         709 :     free_variable(key_a);
     427         709 :     free_variable(key_b);
     428             : 
     429         709 :     return value;
     430             : }
     431             : 
     432             : 
     433             : /**
     434             :  * Prints a file ands its meta data to the screen
     435             :  * @param smeta is the server meta data of the file to be printed on the
     436             :  *        screen
     437             :  */
     438         174 : void print_smeta_to_screen(server_meta_data_t *smeta)
     439             : {
     440         174 :     meta_data_t *meta = NULL;   /**< helper to access smeta->meta structure do not free ! */
     441         174 :     GDateTime *la_date = NULL;
     442         174 :     gchar *the_date = NULL;
     443             : 
     444         174 :     if (smeta !=  NULL && smeta->meta != NULL)
     445             :         {
     446         174 :             meta = smeta->meta;
     447             : 
     448         174 :             switch (meta->file_type)
     449             :                 {
     450             :                     case 1:
     451         165 :                         fprintf(stdout, "[FILE] ");
     452         165 :                     break;
     453             :                     case 2:
     454           9 :                         fprintf(stdout, "[DIR ] ");
     455           9 :                     break;
     456             :                     case 3:
     457           0 :                         fprintf(stdout, "[LINK] ");
     458           0 :                     break;
     459             :                     default:
     460           0 :                         fprintf(stdout, "[    ] ");
     461           0 :                     break;
     462             :                 }
     463             : 
     464         174 :             la_date = g_date_time_new_from_unix_local(meta->mtime);
     465         174 :             the_date = g_date_time_format(la_date, "%F %T %z");
     466             : 
     467         174 :             fprintf(stdout, "%s ", the_date);
     468             : 
     469         174 :             fprintf(stdout, "%s\n", meta->name);
     470             : 
     471         174 :             free_variable(the_date);
     472         174 :             g_date_time_unref(la_date);
     473             :         }
     474             : 
     475         174 : }
     476             : 
     477             : 
     478             : /**
     479             :  * Sets file attributes
     480             :  * @param file is a GFile pointer and must not be null
     481             :  * @param meta is the structure that contains all meta data for the
     482             :  *        file that we want to set.
     483             :  */
     484           4 : void set_file_attributes(GFile *file, meta_data_t *meta)
     485             : {
     486           4 :     GError *error = NULL;
     487           4 :     GFileInfo *fileinfo = NULL;
     488             : 
     489           4 :     if (file != NULL && meta != NULL)
     490             :         {
     491           4 :             fileinfo = g_file_query_info(file, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error);
     492             : 
     493           4 :             if (fileinfo == NULL || error != NULL)
     494             :                 {
     495           0 :                     print_error(__FILE__, __LINE__, _("Error while getting file information: %s\n"), error->message);
     496           0 :                     error = free_error(error);
     497             :                 }
     498             :             else
     499             :                 {
     500           4 :                     set_file_mode_to_gfile(fileinfo, meta);
     501           4 :                     set_dates_to_gfile(fileinfo, meta);
     502             : 
     503           4 :                     if (g_file_set_attributes_from_info(file, fileinfo, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error) == FALSE && error != NULL)
     504             :                         {
     505           4 :                             print_error(__FILE__, __LINE__, _("Error or warning for file (%s): %s\n"), meta->name, error->message);
     506           4 :                             free_error(error);
     507             :                         }
     508             : 
     509           4 :                     free_object(fileinfo);
     510             :                 }
     511             :         }
     512             :     else
     513             :         {
     514             :             /* To translators : do not translate this ! */
     515           0 :             print_error(__FILE__, __LINE__, "set_file_attribute(file = %p, meta = %p)\n", file, meta);
     516             :         }
     517           4 : }
     518             : 
     519             : 
     520             : /**
     521             :  * Makes a symbolic link named  with 'file' filename that points to the
     522             :  * target 'points_to'
     523             :  * @param file is the file to create as a symbolic link
     524             :  * @param points_to is the target of the link
     525             :  */
     526           0 : void make_symbolic_link(GFile *file, gchar *points_to)
     527             : {
     528           0 :     gchar *filename = NULL;
     529           0 :     GError *error = NULL;
     530             : 
     531           0 :     if (file != NULL && points_to != NULL)
     532             :         {
     533           0 :             if (g_file_make_symbolic_link(file, points_to, NULL, &error) == FALSE && error != NULL)
     534             :                 {
     535           0 :                     filename = g_file_get_path(file);
     536           0 :                     print_error(__FILE__, __LINE__, _("Error: unable to create symbolic link %s to %s: %s.\n"), filename, points_to, error->message);
     537           0 :                     free_variable(filename);
     538             :                 }
     539             :         }
     540           0 : }
     541             : 
     542             : 
     543             : /**
     544             :  * Replaces ~ (if found at the first place) by the home directory
     545             :  * of the user.
     546             :  * @param path is a gchar * string that should contain a path
     547             :  * @returns always returns a newly allocated gchar * string that contains
     548             :  *          the normalized path or the path itself;
     549             :  */
     550          10 : gchar *normalize_directory(gchar *path)
     551             : {
     552          10 :     gchar *dircache = NULL;
     553             : 
     554          10 :     if (path != NULL && path[0] == '~')
     555             :         {
     556           0 :             dircache = g_strconcat(g_get_home_dir(), path+1, NULL);
     557             :         }
     558             :     else
     559             :         {
     560          10 :             dircache = g_strdup(path);
     561             :         }
     562             : 
     563          10 :     return dircache;
     564             : }

Generated by: LCOV version 1.11