12e7bf158SAlex Hornung /*
22e7bf158SAlex Hornung * Copyright (c) 2010 The DragonFly Project. All rights reserved.
32e7bf158SAlex Hornung *
42e7bf158SAlex Hornung * This code is derived from software contributed to The DragonFly Project
52e7bf158SAlex Hornung * by Alex Hornung <ahornung@gmail.com>
62e7bf158SAlex Hornung *
72e7bf158SAlex Hornung * Redistribution and use in source and binary forms, with or without
82e7bf158SAlex Hornung * modification, are permitted provided that the following conditions
92e7bf158SAlex Hornung * are met:
102e7bf158SAlex Hornung *
112e7bf158SAlex Hornung * 1. Redistributions of source code must retain the above copyright
122e7bf158SAlex Hornung * notice, this list of conditions and the following disclaimer.
132e7bf158SAlex Hornung * 2. Redistributions in binary form must reproduce the above copyright
142e7bf158SAlex Hornung * notice, this list of conditions and the following disclaimer in
152e7bf158SAlex Hornung * the documentation and/or other materials provided with the
162e7bf158SAlex Hornung * distribution.
172e7bf158SAlex Hornung * 3. Neither the name of The DragonFly Project nor the names of its
182e7bf158SAlex Hornung * contributors may be used to endorse or promote products derived
192e7bf158SAlex Hornung * from this software without specific, prior written permission.
202e7bf158SAlex Hornung *
212e7bf158SAlex Hornung * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
222e7bf158SAlex Hornung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
232e7bf158SAlex Hornung * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
242e7bf158SAlex Hornung * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
252e7bf158SAlex Hornung * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
262e7bf158SAlex Hornung * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
272e7bf158SAlex Hornung * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
282e7bf158SAlex Hornung * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
292e7bf158SAlex Hornung * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
302e7bf158SAlex Hornung * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
312e7bf158SAlex Hornung * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
322e7bf158SAlex Hornung * SUCH DAMAGE.
332e7bf158SAlex Hornung */
342e7bf158SAlex Hornung #include <sys/types.h>
352e7bf158SAlex Hornung #include <sys/device.h>
362e7bf158SAlex Hornung #include <sys/wait.h>
372e7bf158SAlex Hornung #include <sys/socket.h>
382e7bf158SAlex Hornung #include <sys/ioctl.h>
392e7bf158SAlex Hornung #include <sys/poll.h>
402e7bf158SAlex Hornung #include <sys/queue.h>
412e7bf158SAlex Hornung #include <sys/un.h>
422e7bf158SAlex Hornung
432e7bf158SAlex Hornung #include <err.h>
442e7bf158SAlex Hornung #include <errno.h>
452e7bf158SAlex Hornung #include <fcntl.h>
462e7bf158SAlex Hornung #include <libgen.h>
472e7bf158SAlex Hornung #include <regex.h>
482e7bf158SAlex Hornung #include <signal.h>
492e7bf158SAlex Hornung #include <stdarg.h>
502e7bf158SAlex Hornung #include <stdio.h>
512e7bf158SAlex Hornung #include <stdlib.h>
522e7bf158SAlex Hornung #include <string.h>
532e7bf158SAlex Hornung #include <syslog.h>
542e7bf158SAlex Hornung #include <unistd.h>
552e7bf158SAlex Hornung #include <pthread.h>
562e7bf158SAlex Hornung
572e7bf158SAlex Hornung #include <libprop/proplib.h>
582e7bf158SAlex Hornung #include <sys/udev.h>
592e7bf158SAlex Hornung #include "udevd.h"
602e7bf158SAlex Hornung
612e7bf158SAlex Hornung static int64_t udev_generation;
622e7bf158SAlex Hornung TAILQ_HEAD(pdev_array_list_head, pdev_array_entry) pdev_array_list;
632e7bf158SAlex Hornung
642e7bf158SAlex Hornung void
pdev_array_entry_ref(struct pdev_array_entry * pae)652e7bf158SAlex Hornung pdev_array_entry_ref(struct pdev_array_entry *pae)
662e7bf158SAlex Hornung {
672e7bf158SAlex Hornung ++pae->refs;
682e7bf158SAlex Hornung }
692e7bf158SAlex Hornung
702e7bf158SAlex Hornung void
pdev_array_entry_unref(struct pdev_array_entry * pae)712e7bf158SAlex Hornung pdev_array_entry_unref(struct pdev_array_entry *pae)
722e7bf158SAlex Hornung {
732e7bf158SAlex Hornung if (--pae->refs == 0) {
742e7bf158SAlex Hornung TAILQ_REMOVE(&pdev_array_list, pae, link);
752e7bf158SAlex Hornung prop_object_release(pae->pdev_array); /* XXX */
762e7bf158SAlex Hornung free(pae);
772e7bf158SAlex Hornung }
782e7bf158SAlex Hornung }
792e7bf158SAlex Hornung
802e7bf158SAlex Hornung void
pdev_array_entry_insert(prop_array_t pa)812e7bf158SAlex Hornung pdev_array_entry_insert(prop_array_t pa)
822e7bf158SAlex Hornung {
832e7bf158SAlex Hornung struct pdev_array_entry *pae, *opae = NULL;
842e7bf158SAlex Hornung
852e7bf158SAlex Hornung if (pa == NULL)
862e7bf158SAlex Hornung errx(1, "null prop_array in insert_pdev_array");
872e7bf158SAlex Hornung pae = malloc(sizeof(struct pdev_array_entry));
882e7bf158SAlex Hornung if (pae == NULL)
892e7bf158SAlex Hornung errx(1, "insert_pdev_array could not allocate mem");
902e7bf158SAlex Hornung memset(pae, 0, sizeof(struct pdev_array_entry));
912e7bf158SAlex Hornung pae->pdev_array = pa;
922e7bf158SAlex Hornung pae->generation = udev_generation++;
932e7bf158SAlex Hornung pae->refs = 1; /* One ref because it's the most recent one */
942e7bf158SAlex Hornung
952e7bf158SAlex Hornung /*
962e7bf158SAlex Hornung * If the TAILQ is not empty, unref the last entry,
972e7bf158SAlex Hornung * as it isn't needed anymore.
982e7bf158SAlex Hornung */
992e7bf158SAlex Hornung if (!TAILQ_EMPTY(&pdev_array_list))
1002e7bf158SAlex Hornung opae = TAILQ_LAST(&pdev_array_list, pdev_array_list_head);
1012e7bf158SAlex Hornung
1022e7bf158SAlex Hornung TAILQ_INSERT_TAIL(&pdev_array_list, pae, link);
1032e7bf158SAlex Hornung
1042e7bf158SAlex Hornung if (opae != NULL)
1052e7bf158SAlex Hornung pdev_array_entry_unref(opae);
1062e7bf158SAlex Hornung }
1072e7bf158SAlex Hornung
108*9ff03f9eSAlex Hornung void
pdev_array_clean(void)109*9ff03f9eSAlex Hornung pdev_array_clean(void)
110*9ff03f9eSAlex Hornung {
111*9ff03f9eSAlex Hornung struct pdev_array_entry *pae;
112*9ff03f9eSAlex Hornung
113*9ff03f9eSAlex Hornung while ((pae = TAILQ_LAST(&pdev_array_list, pdev_array_list_head)) != NULL) {
114*9ff03f9eSAlex Hornung TAILQ_REMOVE(&pdev_array_list, pae, link);
115*9ff03f9eSAlex Hornung prop_object_release(pae->pdev_array);
116*9ff03f9eSAlex Hornung free(pae);
117*9ff03f9eSAlex Hornung }
118*9ff03f9eSAlex Hornung }
119*9ff03f9eSAlex Hornung
1202e7bf158SAlex Hornung struct pdev_array_entry *
pdev_array_entry_get(int64_t generation)1212e7bf158SAlex Hornung pdev_array_entry_get(int64_t generation)
1222e7bf158SAlex Hornung {
1232e7bf158SAlex Hornung struct pdev_array_entry *pae;
1242e7bf158SAlex Hornung int found = 0;
1252e7bf158SAlex Hornung
1262e7bf158SAlex Hornung TAILQ_FOREACH(pae, &pdev_array_list, link) {
1272e7bf158SAlex Hornung if (pae->generation == generation) {
1282e7bf158SAlex Hornung found = 1;
1292e7bf158SAlex Hornung break;
1302e7bf158SAlex Hornung }
1312e7bf158SAlex Hornung }
1322e7bf158SAlex Hornung
1332e7bf158SAlex Hornung if (!found)
1342e7bf158SAlex Hornung return NULL;
1352e7bf158SAlex Hornung
1362e7bf158SAlex Hornung pdev_array_entry_ref(pae);
1372e7bf158SAlex Hornung return pae;
1382e7bf158SAlex Hornung }
1392e7bf158SAlex Hornung
1402e7bf158SAlex Hornung struct pdev_array_entry *
pdev_array_entry_get_last(void)1412e7bf158SAlex Hornung pdev_array_entry_get_last(void)
1422e7bf158SAlex Hornung {
1432e7bf158SAlex Hornung struct pdev_array_entry *pae;
1442e7bf158SAlex Hornung
1452e7bf158SAlex Hornung pae = TAILQ_LAST(&pdev_array_list, pdev_array_list_head);
1462e7bf158SAlex Hornung
1472e7bf158SAlex Hornung pdev_array_entry_ref(pae);
1482e7bf158SAlex Hornung return pae;
1492e7bf158SAlex Hornung }
150