xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

find.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Vreixo Formoso
3  *
4  * This file is part of the libisofs project; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License version 2
6  * or later as published by the Free Software Foundation.
7  * See COPYING file for details.
8  */
9 
10 #ifdef HAVE_CONFIG_H
11 #include "../config.h"
12 #endif
13 
14 #include "libisofs.h"
15 #include "node.h"
16 
17 #include <fnmatch.h>
18 #include <string.h>
19 
21 {
22  /*
23  * Check whether the given node matches this condition.
24  *
25  * @param cond
26  * The condition to check
27  * @param node
28  * The node that should be checked
29  * @return
30  * 1 if the node matches the condition, 0 if not
31  */
32  int (*matches)(IsoFindCondition *cond, IsoNode *node);
33 
34  /**
35  * Free condition specific data
36  */
38 
39  /** condition specific data */
40  void *data;
41 };
42 
44 {
45  IsoDir *dir; /**< original dir of the iterator */
47  IsoDirIter *itersec; /**< iterator to deal with child dirs */
49  int err; /**< error? */
50  IsoNode *current; /**< node to be returned next */
51  IsoNode *prev; /**< last returned node, needed for removal */
52  int free_cond; /**< whether to free cond on iter_free */
53 };
54 
55 static
56 int get_next(struct find_iter_data *iter, IsoNode **n)
57 {
58  int ret;
59 
60  if (iter->itersec != NULL) {
61  ret = iso_dir_iter_next(iter->itersec, n);
62  if (ret <= 0) {
63  /* secondary item no more needed */
65  iter->itersec = NULL;
66  }
67  if (ret != 0) {
68  /* success or error */
69  return ret;
70  }
71  }
72 
73  /*
74  * we reach here if:
75  * - no secondary item is present
76  * - secondary item has no more items
77  */
78 
79  while ((ret = iso_dir_iter_next(iter->iter, n)) == 1) {
80  if (iter->cond->matches(iter->cond, *n)) {
81  return ISO_SUCCESS;
82  } else if (ISO_NODE_IS_DIR(*n)) {
83  /* recurse on child dir */
84  struct find_iter_data *data;
85  ret = iso_dir_find_children((IsoDir*)*n, iter->cond,
86  &iter->itersec);
87  if (ret < 0) {
88  return ret;
89  }
90  data = iter->itersec->data;
91  data->free_cond = 0; /* we don't need sec iter to free cond */
92  return get_next(iter, n);
93  }
94  }
95  return ret;
96 }
97 
98 static
100 {
101  int ret;
102  IsoNode *n;
103  struct find_iter_data *data = iter->data;
104 
105  if (data->prev) {
106  iso_node_unref(data->prev);
107  }
108  data->prev = data->current;
109 
110  if (data->itersec == NULL && data->current != NULL
111  && ISO_NODE_IS_DIR(data->current)) {
112 
113  /* we need to recurse on child dir */
114  struct find_iter_data *data2;
115  ret = iso_dir_find_children((IsoDir*)data->current, data->cond,
116  &data->itersec);
117  if (ret < 0) {
118  data->current = NULL;
119  data->err = ret;
120  return;
121  }
122  data2 = data->itersec->data;
123  data2->free_cond = 0; /* we don't need sec iter to free cond */
124  }
125 
126  ret = get_next(data, &n);
128  if (ret == 1) {
129  data->current = n;
130  iso_node_ref(n);
131  data->err = 0;
132  iter->dir = n->parent;
133  } else {
134  data->current = NULL;
135  data->err = ret;
136  iter->dir = data->dir;
137  }
139 }
140 
141 static
143 {
144  struct find_iter_data *data;
145 
146  if (iter == NULL || node == NULL) {
147  return ISO_NULL_POINTER;
148  }
149  data = iter->data;
150 
151  if (data->err < 0) {
152  return data->err;
153  }
154  *node = data->current;
155  update_next(iter);
156  return (*node == NULL) ? 0 : ISO_SUCCESS;
157 }
158 
159 static
161 {
162  struct find_iter_data *data = iter->data;
163 
164  return (data->current != NULL);
165 }
166 
167 static
169 {
170  struct find_iter_data *data = iter->data;
171  if (data->free_cond) {
172  data->cond->free(data->cond);
173  free(data->cond);
174  }
175 
176  iso_node_unref((IsoNode*)data->dir);
177 
178  /* free refs to nodes */
179  if (data->prev) {
180  iso_node_unref(data->prev);
181  }
182  if (data->current) {
183  iso_node_unref(data->current);
184  }
185 
186  /* free underlying iter */
187  iso_dir_iter_free(data->iter);
188  free(iter->data);
189 }
190 
191 static
193 {
194  struct find_iter_data *data = iter->data;
195 
196  if (data->prev == NULL) {
197  return ISO_ERROR; /* next not called or end of dir */
198  }
199  return iso_node_take(data->prev);
200 }
201 
202 static
204 {
205  struct find_iter_data *data = iter->data;
206 
207  if (data->prev == NULL) {
208  return ISO_ERROR; /* next not called or end of dir */
209  }
210  return iso_node_remove(data->prev);
211 }
212 
214 {
215  struct find_iter_data *data = iter->data;
216 
217  if (data->prev == node) {
218  /* free our ref */
219  iso_node_unref(node);
220  data->prev = NULL;
221  } else if (data->current == node) {
222  iso_node_unref(node);
223  data->current = NULL;
224  update_next(iter);
225  }
226 }
227 
228 static
236 };
237 
239  IsoDirIter **iter)
240 {
241  int ret;
242  IsoDirIter *children;
243  IsoDirIter *it;
244  struct find_iter_data *data;
245 
246  if (dir == NULL || cond == NULL || iter == NULL) {
247  return ISO_NULL_POINTER;
248  }
249  it = malloc(sizeof(IsoDirIter));
250  if (it == NULL) {
251  return ISO_OUT_OF_MEM;
252  }
253  data = malloc(sizeof(struct find_iter_data));
254  if (data == NULL) {
255  free(it);
256  return ISO_OUT_OF_MEM;
257  }
258  ret = iso_dir_get_children(dir, &children);
259  if (ret < 0) {
260  free(it);
261  free(data);
262  return ret;
263  }
264 
265  it->class = &find_iter_class;
266  it->dir = (IsoDir*)dir;
267  data->iter = children;
268  data->itersec = NULL;
269  data->cond = cond;
270  data->free_cond = 1;
271  data->err = 0;
272  data->prev = data->current = NULL;
273  it->data = data;
274 
275  if (iso_dir_iter_register(it) < 0) {
276  free(it);
277  return ISO_OUT_OF_MEM;
278  }
279 
281 
282  /* take another ref to the original dir */
283  data->dir = (IsoDir*)dir;
285 
286  update_next(it);
287 
288  *iter = it;
289  return ISO_SUCCESS;
290 }
291 
292 /*************** find by name wildcard condition *****************/
293 
294 static
296 {
297  char *pattern = (char*) cond->data;
298  int ret = fnmatch(pattern, node->name, 0);
299  return ret == 0 ? 1 : 0;
300 }
301 
302 static
304 {
305  free(cond->data);
306 }
307 
308 /**
309  * Create a new condition that checks if the node name matches the given
310  * wildcard.
311  *
312  * @param wildcard
313  * @result
314  * The created IsoFindCondition, NULL on error.
315  *
316  * @since 0.6.4
317  */
319 {
321  if (wildcard == NULL) {
322  return NULL;
323  }
324  cond = malloc(sizeof(IsoFindCondition));
325  if (cond == NULL) {
326  return NULL;
327  }
328  cond->data = strdup(wildcard);
331  return cond;
332 }
333 
334 /*************** find by mode condition *****************/
335 
336 static
338 {
339  mode_t *mask = (mode_t*) cond->data;
340  return node->mode & *mask ? 1 : 0;
341 }
342 
343 static
345 {
346  free(cond->data);
347 }
348 
349 /**
350  * Create a new condition that checks the node mode against a mode mask. It
351  * can be used to check both file type and permissions.
352  *
353  * For example:
354  *
355  * iso_new_find_conditions_mode(S_IFREG) : search for regular files
356  * iso_new_find_conditions_mode(S_IFCHR | S_IWUSR) : search for character
357  * devices where owner has write permissions.
358  *
359  * @param mask
360  * Mode mask to AND against node mode.
361  * @result
362  * The created IsoFindCondition, NULL on error.
363  *
364  * @since 0.6.4
365  */
367 {
369  mode_t *data;
370  cond = malloc(sizeof(IsoFindCondition));
371  if (cond == NULL) {
372  return NULL;
373  }
374  data = malloc(sizeof(mode_t));
375  if (data == NULL) {
376  free(cond);
377  return NULL;
378  }
379  *data = mask;
380  cond->data = data;
383  return cond;
384 }
385 
386 /*************** find by gid condition *****************/
387 
388 static
390 {
391  gid_t *gid = (gid_t*) cond->data;
392  return node->gid == *gid ? 1 : 0;
393 }
394 
395 static
397 {
398  free(cond->data);
399 }
400 
401 /**
402  * Create a new condition that checks the node gid.
403  *
404  * @param gid
405  * Desired Group Id.
406  * @result
407  * The created IsoFindCondition, NULL on error.
408  *
409  * @since 0.6.4
410  */
412 {
414  gid_t *data;
415  cond = malloc(sizeof(IsoFindCondition));
416  if (cond == NULL) {
417  return NULL;
418  }
419  data = malloc(sizeof(gid_t));
420  if (data == NULL) {
421  free(cond);
422  return NULL;
423  }
424  *data = gid;
425  cond->data = data;
428  return cond;
429 }
430 
431 /*************** find by uid condition *****************/
432 
433 static
435 {
436  uid_t *uid = (uid_t*) cond->data;
437  return node->uid == *uid ? 1 : 0;
438 }
439 
440 static
442 {
443  free(cond->data);
444 }
445 
446 /**
447  * Create a new condition that checks the node uid.
448  *
449  * @param uid
450  * Desired User Id.
451  * @result
452  * The created IsoFindCondition, NULL on error.
453  *
454  * @since 0.6.4
455  */
457 {
459  uid_t *data;
460  cond = malloc(sizeof(IsoFindCondition));
461  if (cond == NULL) {
462  return NULL;
463  }
464  data = malloc(sizeof(uid_t));
465  if (data == NULL) {
466  free(cond);
467  return NULL;
468  }
469  *data = uid;
470  cond->data = data;
473  return cond;
474 }
475 
476 /*************** find by timestamps condition *****************/
477 
479 {
480  time_t time;
481  int what_time; /* 0 atime, 1 mtime, 2 ctime */
483 };
484 
485 static
487 {
488  time_t node_time;
489  struct cond_times *data = cond->data;
490 
491  switch (data->what_time) {
492  case 0: node_time = node->atime; break;
493  case 1: node_time = node->mtime; break;
494  default: node_time = node->ctime; break;
495  }
496 
497  switch (data->comparison) {
499  return node_time > data->time ? 1 : 0;
501  return node_time >= data->time ? 1 : 0;
502  case ISO_FIND_COND_EQUAL:
503  return node_time == data->time ? 1 : 0;
504  case ISO_FIND_COND_LESS:
505  return node_time < data->time ? 1 : 0;
507  return node_time <= data->time ? 1 : 0;
508  }
509  /* should never happen */
510  return 0;
511 }
512 
513 static
515 {
516  free(cond->data);
517 }
518 
519 /**
520  * Create a new condition that checks the time of last access.
521  *
522  * @param time
523  * Time to compare against IsoNode atime.
524  * @param comparison
525  * Comparison to be done between IsoNode atime and submitted time.
526  * Note that ISO_FIND_COND_GREATER, for example, is true if the node
527  * time is greater than the submitted time.
528  * @result
529  * The created IsoFindCondition, NULL on error.
530  *
531  * @since 0.6.4
532  */
535 {
536  IsoFindCondition *cond;
537  struct cond_times *data;
538  cond = malloc(sizeof(IsoFindCondition));
539  if (cond == NULL) {
540  return NULL;
541  }
542  data = malloc(sizeof(struct cond_times));
543  if (data == NULL) {
544  free(cond);
545  return NULL;
546  }
547  data->time = time;
548  data->comparison = comparison;
549  data->what_time = 0; /* atime */
550  cond->data = data;
551  cond->free = cond_time_free;
552  cond->matches = cond_time_matches;
553  return cond;
554 }
555 
556 /**
557  * Create a new condition that checks the time of last modification.
558  *
559  * @param time
560  * Time to compare against IsoNode mtime.
561  * @param comparison
562  * Comparison to be done between IsoNode mtime and submitted time.
563  * Note that ISO_FIND_COND_GREATER, for example, is true if the node
564  * time is greater than the submitted time.
565  * @result
566  * The created IsoFindCondition, NULL on error.
567  *
568  * @since 0.6.4
569  */
572 {
573  IsoFindCondition *cond;
574  struct cond_times *data;
575  cond = malloc(sizeof(IsoFindCondition));
576  if (cond == NULL) {
577  return NULL;
578  }
579  data = malloc(sizeof(struct cond_times));
580  if (data == NULL) {
581  free(cond);
582  return NULL;
583  }
584  data->time = time;
585  data->comparison = comparison;
586  data->what_time = 1; /* mtime */
587  cond->data = data;
588  cond->free = cond_time_free;
589  cond->matches = cond_time_matches;
590  return cond;
591 }
592 
593 /**
594  * Create a new condition that checks the time of last status change.
595  *
596  * @param time
597  * Time to compare against IsoNode ctime.
598  * @param comparison
599  * Comparison to be done between IsoNode ctime and submitted time.
600  * Note that ISO_FIND_COND_GREATER, for example, is true if the node
601  * time is greater than the submitted time.
602  * @result
603  * The created IsoFindCondition, NULL on error.
604  *
605  * @since 0.6.4
606  */
609 {
610  IsoFindCondition *cond;
611  struct cond_times *data;
612  cond = malloc(sizeof(IsoFindCondition));
613  if (cond == NULL) {
614  return NULL;
615  }
616  data = malloc(sizeof(struct cond_times));
617  if (data == NULL) {
618  free(cond);
619  return NULL;
620  }
621  data->time = time;
622  data->comparison = comparison;
623  data->what_time = 2; /* ctime */
624  cond->data = data;
625  cond->free = cond_time_free;
626  cond->matches = cond_time_matches;
627  return cond;
628 }
629 
630 /*************** logical operations on conditions *****************/
631 
635 };
636 
637 static
639 {
640  struct logical_binary_conditions *data;
641  data = cond->data;
642  data->a->free(data->a);
643  free(data->a);
644  data->b->free(data->b);
645  free(data->b);
646  free(cond->data);
647 }
648 
649 static
651 {
652  struct logical_binary_conditions *data = cond->data;
653  return data->a->matches(data->a, node) && data->b->matches(data->b, node);
654 }
655 
656 /**
657  * Create a new condition that check if the two given conditions are
658  * valid.
659  *
660  * @param a
661  * @param b
662  * IsoFindCondition to compare
663  * @result
664  * The created IsoFindCondition, NULL on error.
665  *
666  * @since 0.6.4
667  */
670 {
671  IsoFindCondition *cond;
672  struct logical_binary_conditions *data;
673  cond = malloc(sizeof(IsoFindCondition));
674  if (cond == NULL) {
675  return NULL;
676  }
677  data = malloc(sizeof(struct logical_binary_conditions));
678  if (data == NULL) {
679  free(cond);
680  return NULL;
681  }
682  data->a = a;
683  data->b = b;
684  cond->data = data;
687  return cond;
688 }
689 
690 static
692 {
693  struct logical_binary_conditions *data = cond->data;
694  return data->a->matches(data->a, node) || data->b->matches(data->b, node);
695 }
696 
697 /**
698  * Create a new condition that check if at least one the two given conditions
699  * is valid.
700  *
701  * @param a
702  * @param b
703  * IsoFindCondition to compare
704  * @result
705  * The created IsoFindCondition, NULL on error.
706  *
707  * @since 0.6.4
708  */
711 {
712  IsoFindCondition *cond;
713  struct logical_binary_conditions *data;
714  cond = malloc(sizeof(IsoFindCondition));
715  if (cond == NULL) {
716  return NULL;
717  }
718  data = malloc(sizeof(struct logical_binary_conditions));
719  if (data == NULL) {
720  free(cond);
721  return NULL;
722  }
723  data->a = a;
724  data->b = b;
725  cond->data = data;
728  return cond;
729 }
730 
731 static
733 {
734  IsoFindCondition *negate = cond->data;
735  negate->free(negate);
736  free(negate);
737 }
738 
739 static
741 {
742  IsoFindCondition *negate = cond->data;
743  return !(negate->matches(negate, node));
744 }
745 
746 /**
747  * Create a new condition that check if the given conditions is false.
748  *
749  * @param negate
750  * @result
751  * The created IsoFindCondition, NULL on error.
752  *
753  * @since 0.6.4
754  */
756 {
757  IsoFindCondition *cond;
758  cond = malloc(sizeof(IsoFindCondition));
759  if (cond == NULL) {
760  return NULL;
761  }
762  cond->data = negate;
763  cond->free = cond_not_free;
764  cond->matches = cond_not_matches;
765  return cond;
766 }
767 
IsoFindCondition * iso_new_find_conditions_mtime(time_t time, enum iso_find_comparisons comparison)
Definition: find.c:570
static int cond_name_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:295
static void cond_logical_binary_free(IsoFindCondition *cond)
Definition: find.c:638
IsoFindCondition * iso_new_find_conditions_and(IsoFindCondition *a, IsoFindCondition *b)
Definition: find.c:668
static void find_iter_free(IsoDirIter *iter)
Definition: find.c:168
static int cond_gid_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:389
static struct iso_dir_iter_iface find_iter_class
Definition: find.c:229
static int find_iter_has_next(IsoDirIter *iter)
Definition: find.c:160
static void update_next(IsoDirIter *iter)
Definition: find.c:99
IsoFindCondition * iso_new_find_conditions_uid(uid_t uid)
Definition: find.c:456
static int cond_logical_and_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:650
IsoFindCondition * iso_new_find_conditions_mode(mode_t mask)
Definition: find.c:366
IsoFindCondition * iso_new_find_conditions_ctime(time_t time, enum iso_find_comparisons comparison)
Definition: find.c:607
static void cond_time_free(IsoFindCondition *cond)
Definition: find.c:514
IsoFindCondition * iso_new_find_conditions_not(IsoFindCondition *negate)
Definition: find.c:755
static void cond_not_free(IsoFindCondition *cond)
Definition: find.c:732
static void cond_gid_free(IsoFindCondition *cond)
Definition: find.c:396
static int find_iter_next(IsoDirIter *iter, IsoNode **node)
Definition: find.c:142
static int find_iter_remove(IsoDirIter *iter)
Definition: find.c:203
static int cond_mode_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:337
static int cond_not_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:740
IsoFindCondition * iso_new_find_conditions_or(IsoFindCondition *a, IsoFindCondition *b)
Definition: find.c:709
IsoFindCondition * iso_new_find_conditions_name(const char *wildcard)
Definition: find.c:318
int iso_dir_find_children(IsoDir *dir, IsoFindCondition *cond, IsoDirIter **iter)
Definition: find.c:238
static void cond_mode_free(IsoFindCondition *cond)
Definition: find.c:344
IsoFindCondition * iso_new_find_conditions_gid(gid_t gid)
Definition: find.c:411
static int cond_uid_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:434
static void cond_uid_free(IsoFindCondition *cond)
Definition: find.c:441
static int get_next(struct find_iter_data *iter, IsoNode **n)
Definition: find.c:56
IsoFindCondition * iso_new_find_conditions_atime(time_t time, enum iso_find_comparisons comparison)
Definition: find.c:533
static int cond_logical_or_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:691
static int find_iter_take(IsoDirIter *iter)
Definition: find.c:192
static int cond_time_matches(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:486
void find_notify_child_taken(IsoDirIter *iter, IsoNode *node)
Definition: find.c:213
static void cond_name_free(IsoFindCondition *cond)
Definition: find.c:303
void iso_node_unref(IsoNode *node)
Definition: node.c:56
#define ISO_SUCCESS
Definition: libisofs.h:8719
int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter)
Definition: node.c:1001
#define ISO_NODE_IS_DIR(n)
Definition: libisofs.h:237
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
int iso_node_take(IsoNode *node)
Definition: node.c:810
void iso_node_ref(IsoNode *node)
Definition: node.c:46
int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node)
Definition: node.c:1035
#define ISO_NULL_POINTER
Definition: libisofs.h:8742
#define ISO_ERROR
Definition: libisofs.h:8734
void iso_dir_iter_free(IsoDirIter *iter)
Definition: node.c:1051
int iso_node_remove(IsoNode *node)
Definition: node.c:850
iso_find_comparisons
Definition: libisofs.h:5553
@ ISO_FIND_COND_LESS
Definition: libisofs.h:5557
@ ISO_FIND_COND_EQUAL
Definition: libisofs.h:5556
@ ISO_FIND_COND_LESS_OR_EQUAL
Definition: libisofs.h:5558
@ ISO_FIND_COND_GREATER_OR_EQUAL
Definition: libisofs.h:5555
@ ISO_FIND_COND_GREATER
Definition: libisofs.h:5554
int iso_dir_iter_register(IsoDirIter *iter)
Definition: node.c:1418
struct iso_dir_iter_iface * class
Definition: node.h:223
IsoDir * dir
Definition: node.h:226
void * data
Definition: node.h:228
Definition: node.h:140
Definition: node.h:100
gid_t gid
Definition: node.h:117
time_t ctime
Definition: node.h:122
uid_t uid
Definition: node.h:116
char * name
Definition: node.h:113
time_t atime
Definition: node.h:120
IsoDir * parent
Definition: node.h:126
mode_t mode
Definition: node.h:115
time_t mtime
Definition: node.h:121
int what_time
Definition: find.c:481
enum iso_find_comparisons comparison
Definition: find.c:482
time_t time
Definition: find.c:480
IsoDirIter * iter
Definition: find.c:46
IsoNode * prev
Definition: find.c:51
IsoFindCondition * cond
Definition: find.c:48
IsoNode * current
Definition: find.c:50
int free_cond
Definition: find.c:52
IsoDirIter * itersec
Definition: find.c:47
IsoDir * dir
Definition: find.c:45
int err
Definition: find.c:49
int(* matches)(IsoFindCondition *cond, IsoNode *node)
Definition: find.c:32
void(* free)(IsoFindCondition *)
Definition: find.c:37
void * data
Definition: find.c:40
IsoFindCondition * a
Definition: find.c:633
IsoFindCondition * b
Definition: find.c:634