Welcome to mirror list, hosted at ThFree Co, Russian Federation.

misc.h « src - github.com/rpm-software-management/createrepo_c.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 60f1a0f8abc3c25ab9ee59d02cb92171c019b326 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
/* createrepo_c - Library of routines for manipulation with repodata
 * Copyright (C) 2012  Tomas Mlcoch
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 */

#ifndef __C_CREATEREPOLIB_MISC_H__
#define __C_CREATEREPOLIB_MISC_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <glib.h>
#include <string.h>
#include <curl/curl.h>
#include "compression_wrapper.h"
#include "xml_parser.h"

/** \defgroup   misc    Miscellaneous useful functions and macros.
 *  \addtogroup misc
 *  @{
 */

/** Lenght of static string (including last '\0' byte)
 */
#define CR_STATICSTRLEN(s) (sizeof(s)/sizeof(s[0]))

/* Length of static defined array.
 */
#define CR_ARRAYLEN(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

/** Convert flags from RPM header to a string representation.
 * @param flags         flags
 * @return              flags as constant string
 */
const char *cr_flag_to_str(gint64 flags);

/** Epoch-Version-Release representation.
 */
typedef struct {
    char *epoch;        /*!< epoch */
    char *version;      /*!< version */
    char *release;      /*!< release */
} cr_EVR;

typedef struct {
    char *name;
    char *epoch;
    char *version;
    char *release;
} cr_NEVR;

typedef struct {
    char *name;
    char *epoch;
    char *version;
    char *release;
    char *arch;
} cr_NEVRA;

/** Version representation
 * e.g. for openssl-devel-1.0.0i = version: 1, release: 0, patch: 0, suffix: i
 */
struct cr_Version {
    long major;         /*!< version */
    long minor;         /*!< release */
    long patch;         /*!< patch */
    char *suffix;       /*!< rest of version string after conversion */
};


/** Convert epoch-version-release string into cr_EVR structure.
 * If no GStringChunk passed, all non NULL items in returned structure
 * are malloced and in that case, you have to free all non-NULL element
 * yourself.
 * @param string        NULL terminated n-v-r string
 * @param chunk         string chunk for strings (optional - could be NULL)
 * @return              filled NVR
 */
cr_EVR *cr_str_to_evr(const char *string, GStringChunk *chunk);

/** Free cr_EVR
 * Warning: Do not use this function when a string chunk was
 * used in the cr_str_to_evr! In that case use only g_free on
 * the cr_EVR pointer.
 * @param evr           cr_EVR structure
 */
void
cr_evr_free(cr_EVR *evr);

/** Check if the filename match pattern for primary files (files listed
 *  in primary.xml).
 * @param filename      full path to file
 * @return              1 if it is primary file, otherwise 0
 */
static inline int cr_is_primary(const char *filename) {
    if (!strncmp(filename, "/etc/", 5))
        return 1;
    if (!strcmp(filename, "/usr/lib/sendmail"))
        return 1;
    if (strstr(filename, "bin/"))
        return 1;
    return 0;
};

/** Header range
 */
struct cr_HeaderRangeStruct {
    unsigned int start;         /*!< First byte of header */
    unsigned int end;           /*!< Last byte of header */
};

/** Return header byte range.
 * @param filename      filename
 * @param err           GError **
 * @return              header range (start = end = 0 on error)
 */
struct cr_HeaderRangeStruct cr_get_header_byte_range(const char *filename,
                                                     GError **err);

/** Return pointer to the rest of string after last '/'.
 * (e.g. for "/foo/bar" returns "bar")
 * @param filepath      path
 * @return              pointer into the path
 */
char *cr_get_filename(const char *filepath);

/** Return pointer to the rest of string after './' prefix.
 * (e.g. for "././foo/bar" returns "foo/bar")
 * @param filepath      path
 * @return              pointer into the path
 */
char *cr_get_cleaned_href(const char *filepath);

/** Download a file from the URL into the in_dst via curl handle.
 * @param handle        CURL handle
 * @param url           source url
 * @param destination   destination (if destination is dir, filename from the
 *                      url is used)
 * @param err           GError **
 * @return              cr_Error
 */
int cr_download(CURL *handle,
                const char *url,
                const char *destination,
                GError **err);

/** Copy file.
 * @param src           source filename
 * @param dst           destination (if dst is dir, filename of src is used)
 * @param err           GError **
 * @return              TRUE on success, FALSE if an error occured
 */
gboolean cr_copy_file(const char *src,
                      const char *dst,
                      GError **err);

/** Compress file.
 * @param SRC           source filename
 * @param DST           destination (If dst is dir, filename of src +
 *                      compression suffix is used.
 *                      If dst is NULL, src + compression suffix is used)
 * @param COMTYPE       type of compression
 * @param ZCK_DICT_DIR  Location of zchunk zdicts (if zchunk is enabled)
 * @param ZCK_AUTO_CHUNK Whether zchunk file should be auto-chunked
 * @param ERR           GError **
 * @return              cr_Error return code
 */
#define cr_compress_file(SRC, DST, COMTYPE, ZCK_DICT_DIR, ZCK_AUTO_CHUNK, ERR) \
                    cr_compress_file_with_stat(SRC, DST, COMTYPE, NULL, ZCK_DICT_DIR, \
                                               ZCK_AUTO_CHUNK, ERR)

/** Compress file.
 * @param src           source filename
 * @param dst           destination (If dst is dir, filename of src +
 *                      compression suffix is used.
 *                      If dst is NULL, src + compression suffix is used)
 * @param comtype       type of compression
 * @param stat          pointer to cr_ContentStat or NULL
 * @param zck_dict_dir  Location of zchunk zdicts (if zchunk is enabled)
 * @param zck_auto_chunk Whether zchunk file should be auto-chunked
 * @param err           GError **
 * @return              cr_Error return code
 */
int cr_compress_file_with_stat(const char *src,
                               const char *dst,
                               cr_CompressionType comtype,
                               cr_ContentStat *stat,
                               const char *zck_dict_dir,
                               gboolean zck_auto_chunk,
                               GError **err);

/** Decompress file.
 * @param SRC           source filename
 * @param DST           destination (If dst is dir, filename of src without
 *                      compression suffix (if present) is used.
 *                      If dst is NULL, src without compression suffix is used)
 *                      Otherwise ".decompressed" suffix is used
 * @param COMTYPE       type of compression
 * @param ERR           GError **
 * @return              cr_Error return code
 */
#define cr_decompress_file(SRC, DST, COMTYPE, ERR) \
                    cr_decompress_file_with_stat(SRC, DST, COMTYPE, NULL, ERR)

/** Decompress file.
 * @param src           source filename
 * @param dst           destination (If dst is dir, filename of src without
 *                      compression suffix (if present) is used.
 *                      If dst is NULL, src without compression suffix is used)
 *                      Otherwise ".decompressed" suffix is used
 * @param comtype       type of compression
 * @param stat          pointer to cr_ContentStat or NULL
 * @param err           GError **
 * @return              cr_Error return code
 */
int cr_decompress_file_with_stat(const char *src,
                                 const char *dst,
                                 cr_CompressionType comtype,
                                 cr_ContentStat *stat,
                                 GError **err);

/** Better copy file. Source (src) could be remote address (http:// or ftp://).
 * @param src           source filename
 * @param dst           destination (if dst is dir, filename of src is used)
 * @param err           GError **
 * @return              TRUE on success, FALSE if an error occured
 */
gboolean cr_better_copy_file(const char *src,
                             const char *dst,
                             GError **err);

/** Recursively remove directory.
 * @param path          filepath
 * @param err           GError **
 * @return              cr_Error return code
 */
int cr_remove_dir(const char *path, GError **err);

/** Normalize path (Path with exactly one trailing '/').
 *@param path           path
 *@return               mallocated string with normalized path or NULL
 */
char *cr_normalize_dir_path(const char *path);

/** Convert version string into cr_Version struct.
 * @param str           version string
 * @return              cr_Version
 */
struct cr_Version cr_str_to_version(const char *str);

/** Compare two version string.
 * @param str1          first version string
 * @param str2          second version string
 * @return              0 - versions are same, 1 - first string is bigger
 *                      version, 2 - second string is bigger version
 */
int cr_cmp_version_str(const char* str1, const char *str2);

/** Logging function with no output.
 * @param log_domain    logging domain
 * @param log_level     logging level
 * @param message       message
 * @param user_data     user data
 */
void cr_null_log_fn(const gchar *log_domain,
                    GLogLevelFlags log_level,
                    const gchar *message,
                    gpointer user_data);

/** Createrepo_c library standard logging function.
 * @param log_domain    logging domain
 * @param log_level     logging level
 * @param message       message
 * @param user_data     user data
 */
void cr_log_fn(const gchar *log_domain,
               GLogLevelFlags log_level,
               const gchar *message,
               gpointer user_data);

/** Frees all the memory used by a GSList, and calls the specified destroy
 * function on every element's data.
 * This is the same function as g_slist_free_full(). The original function
 * is implemented in glib since 2.28 but we need to support the older glib too.
 * @param list          pointer to GSList
 * @param free_f        the function to be called to free each element's data
 */
void cr_slist_free_full(GSList *list, GDestroyNotify free_f);

/** Convenience method, which frees all the memory used by a GQueue,
 * and calls the specified destroy function on every element's data.
 * This is the same function as g_queue_free_full(). The original function
 * is implemented in glib since 2.32 but we need to support the older glib too.
 * @param queue         a pointer to a GQueue
 * @param the function to be called to free each element's data
 */
void cr_queue_free_full(GQueue *queue, GDestroyNotify free_f);

/** Split filename into the NEVRA.
 * Supported formats:
 * [path/]N-V-R:E.A[.rpm]
 * [path/]E:N-V-R.A[.rpm]
 * [path/]N-E:V-R.A[.rpm]
 * [path/]N-V-R.A[.rpm]:E
 * @param filename      filename
 * @return              cr_NEVRA
 */
cr_NEVRA *cr_split_rpm_filename(const char *filename);

/** Compare evr of two cr_NEVRA. Name and arch are ignored.
 * @param A     pointer to first cr_NEVRA
 * @param B     pointer to second cr_NEVRA
 * @return      0 = same, 1 = first is newer, -1 = second is newer
 */
#define cr_cmp_nevra(A, B) (cr_cmp_evr((A)->epoch, (A)->version, (A)->release,\
                                        (B)->epoch, (B)->version, (B)->release))

/** Compare two version strings splited into evr chunks.
 * @param e1     1. epoch
 * @param v1     1. version
 * @param r1     1. release
 * @param e2     2. epoch
 * @param v2     2. version
 * @param r2     2. release
 * @return       0 = same, 1 = first is newer, -1 = second is newer
 */
int cr_cmp_evr(const char *e1, const char *v1, const char *r1,
               const char *e2, const char *v2, const char *r2);


/** Safe insert into GStringChunk.
 * @param chunk     a GStringChunk
 * @param str       string to add or NULL
 * @return          pointer to the copy of str or NULL if str is NULL
 */
static inline gchar *
cr_safe_string_chunk_insert(GStringChunk *chunk, const char *str)
{
    if (!str) return NULL;
    return g_string_chunk_insert(chunk, str);
}

/** Safe insert into GStringChunk with free the str afterwards.
 * @param chunk     a GStringChunk
 * @param str       string to add or NULL
 * @return          pointer to the copy of str on NULL if str was NULL
 */
static inline gchar *
cr_safe_string_chunk_insert_and_free(GStringChunk *chunk, char *str)
{
    if (!str) return NULL;
    gchar *copy = g_string_chunk_insert(chunk, str);
    g_free(str);
    return copy;
}

/** Safe insert into GStringChunk. If str is NULL or "\0" inserts nothing and
 * returns NULL.
 * @param chunk     a GStringChunk
 * @param str       string to add or NULL
 * @return          pointer to the copy of str or NULL if str is NULL
 */
static inline gchar *
cr_safe_string_chunk_insert_null(GStringChunk *chunk, const char *str)
{
    if (!str || *str == '\0') return NULL;
    return g_string_chunk_insert(chunk, str);
}


/** Safe const insert into GStringChunk.
 * @param chunk     a GStringChunk
 * @param str       string to add or NULL
 * @return          pointer to the copy of str or NULL if str is NULL
 */
static inline gchar *
cr_safe_string_chunk_insert_const(GStringChunk *chunk, const char *str)
{
    if (!str) return NULL;
    return g_string_chunk_insert_const(chunk, str);
}

static inline gboolean
cr_key_file_get_boolean_default(GKeyFile *key_file,
                                const gchar *group_name,
                                const gchar *key,
                                gboolean default_value,
                                GError **error)
{
    GError *tmp_err = NULL;
    gboolean ret = g_key_file_get_boolean(key_file, group_name, key, &tmp_err);
    if (tmp_err) {
        g_propagate_error(error, tmp_err);
        return default_value;
    }
    return ret;
}

/** Warning callback for xml parser warnings.
 * For use in xml parsers like primary, filelists, other or repomd parser.
 * Name of the parser should be passed as a string via
 * warning callback data (warningcb_data) argument of the parser.
 */
int
cr_warning_cb(cr_XmlParserWarningType type,
           char *msg,
           void *cbdata,
           GError **err);

/** Open file and write content.
 * @param err       GError **
 * @param filename  Filename
 * @param format    Format string
 * @param ...       Arguments
 */
gboolean
cr_write_to_file(GError **err, gchar *filename, const char *format, ...);

typedef enum {
    CR_CP_DEFAULT       = (1<<0), /*!<
        No attributes - default */
    CR_CP_RECURSIVE     = (1<<1), /*!<
        Copy directories recursively */
    CR_CP_PRESERVE_ALL  = (1<<2), /*!<
        preserve the all attributes (if possible) */
} cr_CpFlags;

/** Recursive copy of directory (works on files as well)
 * @param src           Source (supports wildcards)
 * @param dst           Destination (supports wildcards)
 * @param flags         Flags
 * @param working_dir   Working directory
 * @param err           GError **
 */
gboolean
cr_cp(const char *src,
      const char *dst,
      cr_CpFlags flags,
      const char *working_directory,
      GError **err);

typedef enum {
    CR_RM_DEFAULT       = (1<<0), /*!<
        No attributes - default */
    CR_RM_RECURSIVE     = (1<<1), /*!<
        Copy directories recursively */
    CR_RM_FORCE         = (1<<2), /*!<
        Use force */
} cr_RmFlags;

/** Wrapper over rm command
 * @param path          Path (supports wildcards)
 * @param flags         Flags
 * @param working_dir   Working directory
 * @param err           GError **
 */
gboolean
cr_rm(const char *path,
      cr_RmFlags flags,
      const char *working_dir,
      GError **err);

/** Append "YYYYmmddHHMMSS.MICROSECONDS.PID" suffix to the str.
 * @param str       String or NULL
 * @param suffix    Another string that will be appended or NULL
 * @param return    Newly allocated string
 */
gchar *
cr_append_pid_and_datetime(const char *str, const char *suffix);

/** Createrepo_c's reimplementation of convinient
 * g_spawn_check_exit_status() function which is available since
 * glib 2.34 (createrepo_c is currently compatible with glib >= 2.28)
 * @param exit_status   An exit code as returned from g_spawn_sync()
 * @param error         GError **
 * @returns             TRUE if child exited successfully,
 *                      FALSE otherwise (and error will be set)
 */
gboolean
cr_spawn_check_exit_status(gint exit_status, GError **error);

/** Parse E:N-V-R or N-V-R:E or N-E:V-R string
 * @param str           NEVR string
 * @returns             Malloced cr_NEVR or NULL on error
 */
cr_NEVR *
cr_str_to_nevr(const char *str);

/** Free cr_NEVR
 * @param nevr      cr_NEVR structure
 */
void
cr_nevr_free(cr_NEVR *nevr);

/** Parse E:N-V-R.A, N-V-R:E.A, N-E:V-R.A or N-V-R.A:E string.
 * @param str           NEVRA string
 * @returns             Malloced cr_NEVRA or NULL on error
 */
cr_NEVRA *
cr_str_to_nevra(const char *str);

/** Free cr_NEVRA
 * @param nevra     cr_NEVRA structure
 */
void
cr_nevra_free(cr_NEVRA *nevra);

/** Are the files identical?
 * Different paths could point to the same file.
 * This functions checks if both paths point to the same file or not.
 * If one of the files doesn't exists, the funcion doesn't fail
 * and just put FALSE into "indentical" value and returns.
 * @param fn1           First path
 * @param fn2           Second path
 * @param identical     Are the files same or not
 * @param err           GError **
 * @return              FALSE if an error was encountered, TRUE otherwise
 */
gboolean
cr_identical_files(const gchar *fn1,
                   const gchar *fn2,
                   gboolean *identical,
                   GError **err);

/** Cut first N components of path.
 * Note: Basename is never cut out.
 */
gchar *
cr_cut_dirs(gchar *path, gint cut_dirs);

/** Return string with createrepo_c lib version and available features
 * @return              String with version and list of features
 */
const gchar *
cr_version_string_with_features(void);

/** Get dict file from dict directory
 * This functions returns a zchunk dictionary file from the zchunk dictionary
 * directory that matches the passed filename.  If no zchunk dictionary file
 * exists or no dictionary directory is set, this function returns NULL
 *
 * The zchunk dictionary file must be the same as the passed filename with a
 * ".zdict" extension
 *
 * @param dir           Zchunk dictionary directory
 * @param file          File being zchunked
 * @return              NULL if no matching file exists, or the full path to the
 *                      file otherwise
 */
gchar *
cr_get_dict_file(const gchar *dir,
                 const gchar *file);

/** @} */

#ifdef __cplusplus
}
#endif

#endif /* __C_CREATEREPOLIB_MISC_H__ */