~vorlon/ubuntu/raring/upstart/lp.1199778

« back to all changes in this revision

Viewing changes to init/conf.c

  • Committer: Scott James Remnant
  • Date: 2007-11-03 06:06:54 UTC
  • Revision ID: scott@netsplit.com-20071103060654-86lrh9zxcg5nj33z
* init/conf.h (ConfSource): Remove priority, we'll place these
in a linked list and use that order instead.
(ConfSourcePriority): Drop accordingly.
(ConfItem): Drop this structure; permitting jobs and states to be
defined inside larger conf files made things complicated for no
benefit; move the item union into
(ConfFile): here, instead of the items list.
(ConfItemType): Drop accordingly.
* init/conf.c (conf_init): Store sources in a linked list, instead
of a hash table; no idea why it ever was.
(conf_source_new): Drop priority argument and add to list not hash.
(conf_file_new): Set data to NULL instead of initialising items,
set destructor to conf_file_destroy.
(conf_item_destroy): Rename to conf_file_destroy
(conf_file_destroy): and adjust to refer to ConfItem instead,
getting the item type through the source.
(conf_item_new): Drop.
(conf_reload): Iterate as linked list not hash table.
(conf_reload_path): Simplify handling of old files and items a
little, just look it up and always free if it exists before parsing
the new file.
(conf_file_get): No longer any need for this function.
* init/tests/test_conf.c (test_file_get, test_item_new): Drop
test functions for those that have been removed.
(test_item_destroy): Rename to test_file_destroy.
(test_source_new): Don't pass or check priority, or hash lookup.
(test_file_new): Check data is set correctly.
(test_source_reload_job_dir, test_source_reload_conf_dir)
(test_source_reload_file): Update tests accordingly.
* init/parse_conf.c (stanza_job): Drop the job stanza, jobs
may only be defined in dedicated directories.  
* init/tests/test_parse_conf.c (test_parse_conf): Simply check to only
make sure the file is parsed.
(test_stanza_job): Drop function.
* init/main.c: Update calls to conf_source_new.
* init/init.supp: Update intermediate function in suppression.

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
/**
76
76
 * conf_sources:
77
77
 *
78
 
 * This hash table holds the list of known sources of configurations,
79
 
 * indexed by their path.  Each entry is a ConfSource structure, multiple
80
 
 * entries for the same path may not exist.
 
78
 * This list holds the list of known sources of configuration; each item
 
79
 * is a ConfSource structure.  The order of this list dictates the priority
 
80
 * of the sources, with the first one having the highest priority.
81
81
 **/
82
 
NihHash *conf_sources = NULL;
 
82
NihList *conf_sources = NULL;
83
83
 
84
84
 
85
85
/**
86
86
 * conf_init:
87
87
 *
88
 
 * Initialise the conf_sources hash table.
 
88
 * Initialise the conf_sources list.
89
89
 **/
90
90
void
91
91
conf_init (void)
92
92
{
93
93
        if (! conf_sources)
94
 
                NIH_MUST (conf_sources = nih_hash_new (NULL, 0,
95
 
                                                       (NihKeyFunction)nih_hash_string_key));
 
94
                NIH_MUST (conf_sources = nih_list_new (NULL));
96
95
}
97
96
 
98
97
 
100
99
 * conf_source_new:
101
100
 * @parent: parent of new block,
102
101
 * @path: path to source,
103
 
 * @type: type of source,
104
 
 * @priority: priority for selection.
 
102
 * @type: type of source.
105
103
 *
106
104
 * Allocates and returns a new ConfSource structure for the given @path;
107
105
 * @type indicates whether this @path is a file or directory and what type
108
 
 * of files are within the directory; @priority is used when multiple items
109
 
 * have the same name.
 
106
 * of files are within the directory.
110
107
 *
111
 
 * The returned structure is automatically placed in the conf_sources hash
112
 
 * table, indexed by @path.
 
108
 * The returned structure is automatically added to the conf_sources list.
113
109
 *
114
110
 * Configuration is not parsed immediately, instead you must call
115
111
 * conf_source_reload() on this source to set up any watches and load the
124
120
 * insufficient memory.
125
121
 **/
126
122
ConfSource *
127
 
conf_source_new (const void         *parent,
128
 
                 const char         *path,
129
 
                 ConfSourceType      type,
130
 
                 ConfSourcePriority  priority)
 
123
conf_source_new (const void     *parent,
 
124
                 const char     *path,
 
125
                 ConfSourceType  type)
131
126
{
132
127
        ConfSource *source;
133
128
 
148
143
        }
149
144
 
150
145
        source->type = type;
151
 
        source->priority = priority;
152
 
 
153
146
        source->watch = NULL;
154
147
 
155
148
        source->flag = FALSE;
162
155
 
163
156
        nih_alloc_set_destructor (source, (NihDestructor)nih_list_destroy);
164
157
 
165
 
        nih_hash_add (conf_sources, &source->entry);
 
158
        nih_list_add (conf_sources, &source->entry);
166
159
 
167
160
        return source;
168
161
}
175
168
 * Allocates and returns a new ConfFile structure for the given @source,
176
169
 * with @path indicating which file it is.
177
170
 *
178
 
 * The returned structure is automatically placed in the @source files hash
 
171
 * The returned structure is automatically placed in the @source's files hash
179
172
 * and the flag of the returned ConfFile will be set to that of the @source.
180
173
 *
181
174
 * Returns: newly allocated ConfFile structure or NULL if insufficient memory.
195
188
 
196
189
        nih_list_init (&file->entry);
197
190
 
198
 
        file->source = source;
199
 
 
200
191
        file->path = nih_strdup (file, path);
201
192
        if (! file->path) {
202
193
                nih_free (file);
203
194
                return NULL;
204
195
        }
205
196
 
206
 
        nih_list_init (&file->items);
 
197
        file->source = source;
 
198
        file->flag = source->flag;
 
199
        file->data = NULL;
207
200
 
208
 
        nih_alloc_set_destructor (file, (NihDestructor)nih_list_destroy);
 
201
        nih_alloc_set_destructor (file, (NihDestructor)conf_file_destroy);
209
202
 
210
203
        nih_hash_add (source->files, &file->entry);
211
204
 
212
 
        file->flag = source->flag;
213
 
 
214
 
        return file;
215
 
}
216
 
 
217
 
/**
218
 
 * conf_file_get:
219
 
 * @source: configuration source,
220
 
 * @path: path to file.
221
 
 *
222
 
 * Looks up the ConfFile entry in @source for @path, or allocates a new
223
 
 * structure and places it in the files hash table before returning it.
224
 
 *
225
 
 * The flag of the returned ConfFile will be set to that of the @source.
226
 
 *
227
 
 * Returns: existing or newly allocated ConfFile structure,
228
 
 * or NULL if insufficient memory.
229
 
 **/
230
 
ConfFile *
231
 
conf_file_get (ConfSource *source,
232
 
               const char *path)
233
 
{
234
 
        ConfFile *file;
235
 
 
236
 
        nih_assert (source != NULL);
237
 
        nih_assert (path != NULL);
238
 
 
239
 
        file = (ConfFile *)nih_hash_lookup (source->files, path);
240
 
        if (file) {
241
 
                file->flag = source->flag;
242
 
        } else {
243
 
                file = conf_file_new (source, path);
244
 
        }
245
 
 
246
 
        return file;
247
 
}
248
 
 
249
 
/**
250
 
 * conf_item_new:
251
 
 * @file: file to attach to,
252
 
 * @type: type of item.
253
 
 *
254
 
 * Allocates and returns a new ConfItem structure for the given @file,
255
 
 * with @type indicating what kind of data will be attached
256
 
 * to this item.  Setting the data pointer is the job of the caller.
257
 
 *
258
 
 * The returned structure is automatically placed in the @file items list.
259
 
 *
260
 
 * Returns: newly allocated ConfItem structure or NULL if insufficient memory.
261
 
 **/
262
 
ConfItem *
263
 
conf_item_new (ConfFile     *file,
264
 
               ConfItemType  type)
265
 
{
266
 
        ConfItem *item;
267
 
 
268
 
        nih_assert (file != NULL);
269
 
 
270
 
        item = nih_new (file, ConfItem);
271
 
        if (! item)
272
 
                return NULL;
273
 
 
274
 
        nih_list_init (&item->entry);
275
 
 
276
 
        item->file = file;
277
 
        item->type = type;
278
 
        item->data = NULL;
279
 
 
280
 
        nih_alloc_set_destructor (item, (NihDestructor)conf_item_destroy);
281
 
 
282
 
        nih_list_add (&file->items, &item->entry);
283
 
 
284
 
        return item;
 
205
        return file;
285
206
}
286
207
 
287
208
 
303
224
{
304
225
        conf_init ();
305
226
 
306
 
        NIH_HASH_FOREACH (conf_sources, iter) {
 
227
        NIH_LIST_FOREACH (conf_sources, iter) {
307
228
                ConfSource *source = (ConfSource *)iter;
308
229
 
309
230
                if (conf_source_reload (source) < 0) {
389
310
 * and parsed.  It is the parent directory because we need to watch out for
390
311
 * editors that rename over the top, etc.
391
312
 *
392
 
 * We then parse the current state of the file, propogating the value of
393
 
 * the flag member to all items that we find so that deletions can be
394
 
 * detected by the calling function.
395
 
 *
396
313
 * Returns: zero on success, negative value on raised error.
397
314
 **/
398
315
static int
468
385
 * tree.
469
386
 *
470
387
 * Otherwise we walk the tree ourselves and parse all files that we find,
471
 
 * propogating the value of the flag member to all files and items so that
472
 
 * deletion can be detected by the calling function.
 
388
 * propogating the value of the flag member to all files so that deletion
 
389
 * can be detected by the calling function.
473
390
 *
474
391
 * Returns: zero on success, negative value on raised error.
475
392
 **/
616
533
 * filtered to only return the path that we're interested in.
617
534
 *
618
535
 * We lookup the file in our hash table, and if we can find it, perform
619
 
 * the usual deletion on all of its items and the file itself.
 
536
 * the usual deletion of it.
620
537
  **/
621
538
static void
622
539
conf_delete_handler (ConfSource *source,
697
614
 * @path: path of file to be reloaded.
698
615
 *
699
616
 * This function is used to parse the file at @path in the context of the
700
 
 * given configuration @source.  Necessary ConfFile and ConfItem structures
701
 
 * are allocated and attached to the @source as appropriate.
702
 
 *
703
 
 * Depending on the type of the @source, this can parse jobs directly (in
704
 
 * which case they are named after the relative part of the path) or mixed
705
 
 * configuration files which define the names specifically.
706
 
 *
707
 
 * If the file has been parsed before, then any existing items are deleted
708
 
 * and freed if the file fails to load, or after the new items have been
709
 
 * parsed.  Items are not reused for the same apparent item between reloads,
710
 
 * since there's no real meaning to it.
 
617
 * given configuration @source.  Necessary ConfFile structures are allocated
 
618
 * and attached to @source as appropriate.  CONF_FILE sources always have
 
619
 * a single ConfFile when the file exists.
 
620
 *
 
621
 * If the file has been parsed before, then the existing item is deleted and
 
622
 * freed if the file fails to load, or after the new item has been parsed.
 
623
 * Items are not reused between reloads.
711
624
 *
712
625
 * Physical errors are returned, parse errors are not.
713
626
 *
718
631
                  const char *path)
719
632
{
720
633
        ConfFile   *file;
721
 
        NihList     old_items;
722
 
        ConfItem   *item;
723
634
        const char *buf, *name;
724
635
        size_t      len, pos, lineno;
725
636
        NihError   *err = NULL;
727
638
        nih_assert (source != NULL);
728
639
        nih_assert (path != NULL);
729
640
 
730
 
        NIH_MUST (file = conf_file_get (source, path));
731
 
 
732
 
        /* Map the file into memory for parsing.  If this fails, then we
733
 
         * delete all the current items since there's clearly a problem.
734
 
         */
735
 
        buf = nih_file_map (file->path, O_RDONLY | O_NOCTTY, &len);
736
 
        if (! buf) {
737
 
                NIH_LIST_FOREACH_SAFE (&file->items, iter) {
738
 
                        ConfItem *item = (ConfItem *)iter;
739
 
 
740
 
                        nih_free (item);
741
 
                }
742
 
 
 
641
        /* Look up the old file in memory, and then free it.  In cases
 
642
         * of failure, we discard it anyway, so there's no particular reason
 
643
         * to keep it around anymore.
 
644
         */
 
645
        file = (ConfFile *)nih_hash_lookup (source->files, path);
 
646
        if (file)
 
647
                nih_free (file);
 
648
 
 
649
        /* Map the file into memory for parsing, if this fails we don't
 
650
         * bother creating a new ConfFile structure for it and bail out
 
651
         * now.
 
652
         */
 
653
        buf = nih_file_map (path, O_RDONLY | O_NOCTTY, &len);
 
654
        if (! buf)
743
655
                return -1;
744
 
        }
745
 
 
746
 
        /* If we've parsed this file before, we'll have a list of old items
747
 
         * that once existed and need to be cleaned up once we've parsed
748
 
         * the new items.  The easiest way to identify them is to put
749
 
         * them into a different list for safe-keeping.
750
 
         */
751
 
        nih_list_init (&old_items);
752
 
        nih_list_add (&file->items, &old_items);
753
 
        nih_list_remove (&file->items);
754
 
 
755
 
        /* Parse the file buffer, registering items found against the
756
 
         * ConfFile; the existing items are removed later.
757
 
         */
 
656
 
 
657
        /* Parse the file, storing the item in a new ConfFile structure. */
 
658
        NIH_MUST (file = conf_file_new (source, path));
 
659
 
758
660
        pos = 0;
759
661
        lineno = 1;
760
662
 
761
663
        switch (source->type) {
762
664
        case CONF_FILE:
763
665
        case CONF_DIR:
764
 
                /* Parse the file, this deals with item creation itself
765
 
                 * since only it knows the item types and names.
766
 
                 */
 
666
                /* Simple file of options; usually no item attached to it. */
767
667
                nih_debug ("Loading configuration from %s", path);
768
668
                if (parse_conf (file, buf, len, &pos, &lineno) < 0)
769
669
                        err = nih_error_get ();
781
681
                        name++;
782
682
 
783
683
                /* Create a new job item and parse the buffer to produce
784
 
                 * the job definition.  Discard the item if this fails.
 
684
                 * the job definition.
785
685
                 */
786
686
                nih_debug ("Loading %s from %s", name, path);
787
 
                NIH_MUST (item = conf_item_new (file, CONF_JOB));
788
 
                item->job = parse_job (NULL, name, buf, len, &pos, &lineno);
789
 
                if (! item->job) {
 
687
                file->job = parse_job (NULL, name, buf, len, &pos, &lineno);
 
688
                if (! file->job)
790
689
                        err = nih_error_get ();
791
690
 
792
 
                        nih_free (item);
793
 
                }
794
 
 
795
691
                break;
796
692
        default:
797
693
                nih_assert_not_reached ();
824
720
                }
825
721
        }
826
722
 
827
 
        /* Delete the old items now we've parsed in the list of new ones.
828
 
         */
829
 
        NIH_LIST_FOREACH_SAFE (&old_items, iter) {
830
 
                ConfItem *item = (ConfItem *)iter;
831
 
 
832
 
                nih_free (item);
833
 
        }
834
 
 
835
723
        /* Unmap the file again; in theory this shouldn't fail, but if
836
724
         * it does, return an error condition even though we've actually
837
725
         * loaded some of the new things.
855
743
 
856
744
 
857
745
/**
858
 
 * conf_item_destructor:
859
 
 * @item: configuration item to be destroyed.
 
746
 * conf_file_destroy:
 
747
 * @file: configuration file to be destroyed.
860
748
 *
861
 
 * Handles the replacement and deletion of the item itself.
 
749
 * Handles the replacement and deletion of a configuration file, ensuring
 
750
 * that @file is removed from the containing linked list and that the item
 
751
 * attached to it is destroyed if not currently in use.
862
752
 *
863
753
 * Normally used or called from an nih_alloc() destructor so that the list
864
754
 * item is automatically removed from its containing list when freed.
866
756
 * Returns: zero.
867
757
 **/
868
758
int
869
 
conf_item_destroy (ConfItem *item)
 
759
conf_file_destroy (ConfFile *file)
870
760
{
871
 
        nih_assert (item != NULL);
 
761
        nih_assert (file != NULL);
872
762
 
873
 
        switch (item->type) {
874
 
        case CONF_JOB:
875
 
                if (! item->job)
 
763
        switch (file->source->type) {
 
764
        case CONF_FILE:
 
765
        case CONF_DIR:
 
766
                break;
 
767
        case CONF_JOB_DIR:
 
768
                if (! file->job)
876
769
                        break;
877
770
 
878
771
                /* If the item being deleted hasn't already been marked for
879
772
                 * replacement, mark it for deletion.
880
773
                 */
881
 
                if (! item->job->replacement)
882
 
                        item->job->replacement = (void *)-1;
 
774
                if (! file->job->replacement)
 
775
                        file->job->replacement = (void *)-1;
883
776
 
884
777
                /* If the item being deleted is the replacement for another,
885
778
                 * cut out the middle man and make that item's replacement
886
779
                 * the same as our own replacement (ie. probably deletion)
887
780
                 */
888
 
                if ((item->job->replacement_for != NULL)
889
 
                    && (item->job->replacement_for->replacement == item->job))
890
 
                        item->job->replacement_for->replacement \
891
 
                                = item->job->replacement;
 
781
                if ((file->job->replacement_for != NULL)
 
782
                    && (file->job->replacement_for->replacement == file->job))
 
783
                        file->job->replacement_for->replacement \
 
784
                                = file->job->replacement;
892
785
 
893
786
                /* Delete the job if we can */
894
 
                if (job_config_should_replace (item->job)) {
 
787
                if (job_config_should_replace (file->job)) {
895
788
                        /* If the item being deleted has a replacement, ensure
896
789
                         * that the replacement doesn't reference it anymore.
897
790
                         */
898
 
                        if ((item->job->replacement != NULL)
899
 
                            && (item->job->replacement != (void *)-1)
900
 
                            && (item->job->replacement->replacement_for == item->job))
901
 
                                item->job->replacement->replacement_for = NULL;
 
791
                        if ((file->job->replacement != NULL)
 
792
                            && (file->job->replacement != (void *)-1)
 
793
                            && (file->job->replacement->replacement_for == file->job))
 
794
                                file->job->replacement->replacement_for = NULL;
902
795
 
903
 
                        nih_free (item->job);
 
796
                        nih_free (file->job);
904
797
                }
905
798
 
906
799
                break;
 
800
        default:
 
801
                nih_assert_not_reached ();
907
802
        }
908
803
 
909
 
        nih_list_destroy (&item->entry);
 
804
        nih_list_destroy (&file->entry);
910
805
 
911
806
        return 0;
912
807
}