source: rtems/cpukit/libblock/src/media.c

Last change on this file was 0d5319d, checked in by Kinsey Moore <kinsey.moore@…>, on 01/24/24 at 17:52:45

cpukit/libblock: Ignore error notify return value

This is already in the error path.

  • Property mode set to 100644
File size: 20.7 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSMedia
7 *
8 * @brief Media implementation.
9 */
10
11/*
12 * Copyright (C) 2009, 2013 embedded brains GmbH & Co. KG
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <stdlib.h>
37#include <string.h>
38#include <assert.h>
39#include <unistd.h>
40
41#include <rtems/media.h>
42
43#include <rtems.h>
44#include <rtems/bdbuf.h>
45#include <rtems/blkdev.h>
46#include <rtems/bdpart.h>
47#include <rtems/libio.h>
48#include <rtems/dosfs.h>
49#include <rtems/thread.h>
50
51typedef struct {
52  rtems_bdpart_partition *partitions;
53  size_t *count;
54} partition_table;
55
56typedef struct {
57  size_t index;
58  rtems_blkdev_bnum begin;
59  rtems_blkdev_bnum count;
60} partition;
61
62typedef struct media_item {
63  rtems_chain_node node;
64  struct media_item *parent;
65  char *disk_path;
66  char *mount_path;
67} media_item;
68
69typedef struct listener_item {
70  rtems_chain_node node;
71  rtems_media_listener listener;
72  void *listener_arg;
73} listener_item;
74
75static RTEMS_CHAIN_DEFINE_EMPTY(listener_item_chain);
76
77static RTEMS_CHAIN_DEFINE_EMPTY(media_item_chain);
78
79static rtems_mutex media_mutex = RTEMS_MUTEX_INITIALIZER("Media");
80
81static void lock(void)
82{
83  rtems_mutex_lock(&media_mutex);
84}
85
86static void unlock(void)
87{
88  rtems_mutex_unlock(&media_mutex);
89}
90
91static listener_item *find_listener(
92  rtems_media_listener listener,
93  void *listener_arg
94)
95{
96  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
97
98  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
99    listener_item *item = (listener_item *) node;
100
101    if (item->listener == listener && item->listener_arg == listener_arg) {
102      return item;
103    }
104
105    node = rtems_chain_next(node);
106  }
107
108  return NULL;
109}
110
111rtems_status_code rtems_media_listener_add(
112  rtems_media_listener listener,
113  void *listener_arg
114)
115{
116  rtems_status_code sc = RTEMS_SUCCESSFUL;
117  listener_item *item;
118
119  lock();
120
121  item = find_listener(listener, listener_arg);
122
123  if (item == NULL) {
124    item = malloc(sizeof(*item));
125    if (item != NULL) {
126      item->listener = listener;
127      item->listener_arg = listener_arg;
128      rtems_chain_initialize_node(&item->node);
129      rtems_chain_append_unprotected(&listener_item_chain, &item->node);
130    } else {
131      sc = RTEMS_NO_MEMORY;
132    }
133  } else {
134    sc = RTEMS_TOO_MANY;
135  }
136
137  unlock();
138
139  return sc;
140}
141
142rtems_status_code rtems_media_listener_remove(
143  rtems_media_listener listener,
144  void *listener_arg
145)
146{
147  rtems_status_code sc = RTEMS_SUCCESSFUL;
148  listener_item *item;
149
150  lock();
151
152  item = find_listener(listener, listener_arg);
153
154  if (item != NULL) {
155    rtems_chain_extract_unprotected(&item->node);
156    free(item);
157  } else {
158    sc = RTEMS_INVALID_ID;
159  }
160
161  unlock();
162
163  return sc;
164}
165
166static rtems_status_code notify(
167  rtems_media_event event,
168  rtems_media_state state,
169  const char *src,
170  const char *dest
171)
172{
173  rtems_status_code sc = RTEMS_SUCCESSFUL;
174  rtems_status_code rsc = RTEMS_SUCCESSFUL;
175  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
176
177  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
178    listener_item *item = (listener_item *) node;
179
180    sc = (*item->listener)(event, state, src, dest, item->listener_arg);
181    if (sc != RTEMS_SUCCESSFUL) {
182      rsc = sc;
183    }
184
185    node = rtems_chain_next(node);
186  }
187
188  return rsc;
189}
190
191static void error(
192  rtems_media_state state,
193  const char *src,
194  const char *dest
195)
196{
197  (void) notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest);
198}
199
200static media_item *get_media_item(
201  const char *disk_path,
202  const char *mount_path
203)
204{
205  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
206
207  while (!rtems_chain_is_tail(&media_item_chain, node)) {
208    media_item *item = (media_item *) node;
209
210    if (
211      (disk_path == NULL || strcmp(disk_path, item->disk_path) == 0)
212        && (mount_path == NULL
213          || (item->mount_path != NULL
214            && strcmp(mount_path, item->mount_path) == 0))
215    ) {
216      return item;
217    }
218
219    node = rtems_chain_next(node);
220  }
221
222  return NULL;
223}
224
225static void free_item(media_item *item)
226{
227  rtems_chain_extract_unprotected(&item->node);
228  free(item->mount_path);
229  free(item);
230}
231
232static void create_item(
233  media_item *parent,
234  const char *disk_path,
235  const char *mount_path
236)
237{
238  size_t disk_path_size = strlen(disk_path) + 1;
239  media_item *item = malloc(sizeof(*item) + disk_path_size);
240
241  if (item != NULL) {
242    if (mount_path != NULL) {
243      item->mount_path = strdup(mount_path);
244
245      if (item->mount_path == NULL) {
246        free(item);
247
248        return;
249      }
250    } else {
251      item->mount_path = NULL;
252    }
253
254    item->parent = parent;
255    item->disk_path = (char *) item + sizeof(*item);
256    memcpy(item->disk_path, disk_path, disk_path_size);
257    rtems_chain_initialize_node(&item->node);
258    rtems_chain_append(&media_item_chain, &item->node);
259  }
260}
261
262static void remove_mount_point(const char *mount_path)
263{
264  media_item *item = get_media_item(NULL, mount_path);
265
266  if (item != NULL) {
267    free(item->mount_path);
268    item->mount_path = NULL;
269  } else {
270    error(RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN, mount_path, NULL);
271  }
272}
273
274static void remove_partition(const char *partition_path)
275{
276  media_item *item = get_media_item(partition_path, NULL);
277
278  if (item != NULL) {
279    if (item->mount_path != NULL) {
280      error(
281        RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
282        partition_path,
283        item->mount_path
284      );
285    }
286    free_item(item);
287  } else {
288    error(RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN, partition_path, NULL);
289  }
290}
291
292static void remove_disk(const char *disk_path)
293{
294  media_item *item = get_media_item(disk_path, NULL);
295
296  if (item != NULL) {
297    rtems_chain_node *node = rtems_chain_first(&media_item_chain);
298
299    while (!rtems_chain_is_tail(&media_item_chain, node)) {
300      media_item *child = (media_item *) node;
301
302      node = rtems_chain_next(node);
303
304      if (child->parent == item) {
305        if (child->mount_path != NULL) {
306          error(
307            RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN,
308            child->mount_path,
309            disk_path
310          );
311        }
312        error(RTEMS_MEDIA_ERROR_PARTITION_ORPHAN, child->disk_path, disk_path);
313        free_item(child);
314      }
315    }
316
317    free_item(item);
318  } else {
319    error(RTEMS_MEDIA_ERROR_DISK_UNKNOWN, disk_path, NULL);
320  }
321}
322
323static void add_disk(const char *disk_path)
324{
325  media_item *item = get_media_item(disk_path, NULL);
326
327  if (item != NULL) {
328    error(RTEMS_MEDIA_ERROR_DISK_EXISTS, disk_path, NULL);
329    remove_disk(disk_path);
330  }
331
332  create_item(NULL, disk_path, NULL);
333}
334
335static void add_partition(const char *disk_path, const char *partition_path)
336{
337  media_item *item = get_media_item(partition_path, NULL);
338  media_item *parent = get_media_item(disk_path, NULL);
339
340  if (item != NULL) {
341    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS, partition_path, NULL);
342    remove_disk(partition_path);
343  }
344
345  if (parent != NULL) {
346    create_item(parent, partition_path, NULL);
347  } else {
348    error(
349      RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
350      partition_path,
351      disk_path
352    );
353  }
354}
355
356static void add_mount_point(const char *disk_path, const char *mount_path)
357{
358  media_item *item = get_media_item(disk_path, NULL);
359
360  if (item != NULL) {
361    if (item->mount_path != NULL) {
362      error(RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS, item->mount_path, NULL);
363      free(item->mount_path);
364    }
365    item->mount_path = strdup(mount_path);
366  } else {
367    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN, disk_path, NULL);
368  }
369}
370
371static bool is_add_state(rtems_media_state state)
372{
373  return state == RTEMS_MEDIA_STATE_SUCCESS;
374}
375
376static bool is_remove_state(rtems_media_state state)
377{
378  return state == RTEMS_MEDIA_STATE_SUCCESS
379    || state == RTEMS_MEDIA_STATE_FAILED;
380}
381
382static rtems_status_code remember_event(
383  rtems_media_event event,
384  rtems_media_state state,
385  const char *src,
386  const char *dest
387)
388{
389  switch (event) {
390    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
391      if (is_add_state(state)) {
392        add_disk(dest);
393      }
394      break;
395    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
396      if (is_add_state(state)) {
397        add_partition(src, dest);
398      }
399      break;
400    case RTEMS_MEDIA_EVENT_MOUNT:
401      if (is_add_state(state)) {
402        add_mount_point(src, dest);
403      }
404      break;
405    case RTEMS_MEDIA_EVENT_UNMOUNT:
406      if (is_remove_state(state)) {
407        remove_mount_point(src);
408      }
409      break;
410    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
411      if (is_remove_state(state)) {
412        remove_partition(src);
413      }
414      break;
415    case RTEMS_MEDIA_EVENT_DISK_DETACH:
416      if (is_remove_state(state)) {
417        remove_disk(src);
418      }
419      break;
420    default:
421      break;
422  }
423
424  return RTEMS_SUCCESSFUL;
425}
426
427static rtems_status_code process_event(
428  rtems_media_event event,
429  const char *src,
430  char **dest_ptr,
431  rtems_media_worker worker,
432  void *worker_arg
433)
434{
435  rtems_status_code sc = RTEMS_SUCCESSFUL;
436  rtems_status_code sc_retry = RTEMS_SUCCESSFUL;
437  rtems_media_state state;
438  char *dest = NULL;
439
440  do {
441    sc = notify(event, RTEMS_MEDIA_STATE_INQUIRY, src, NULL);
442    if (sc == RTEMS_SUCCESSFUL) {
443      state = RTEMS_MEDIA_STATE_READY;
444    } else {
445      state = RTEMS_MEDIA_STATE_ABORTED;
446    }
447
448    sc = (*worker)(state, src, &dest, worker_arg);
449    if (state == RTEMS_MEDIA_STATE_READY) {
450      if (sc == RTEMS_SUCCESSFUL) {
451        state = RTEMS_MEDIA_STATE_SUCCESS;
452      } else {
453        state = RTEMS_MEDIA_STATE_FAILED;
454      }
455    }
456
457    sc_retry = notify(event, state, src, dest);
458  } while (state == RTEMS_MEDIA_STATE_FAILED
459    && sc_retry == RTEMS_INCORRECT_STATE);
460  remember_event(event, state, src, dest);
461
462  if (state == RTEMS_MEDIA_STATE_SUCCESS) {
463    sc = RTEMS_SUCCESSFUL;
464  } else if (state == RTEMS_MEDIA_STATE_ABORTED) {
465    sc = RTEMS_UNSATISFIED;
466  } else {
467    sc = RTEMS_IO_ERROR;
468  }
469
470  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
471    *dest_ptr = dest;
472  } else {
473    free(dest);
474  }
475
476  return sc;
477}
478
479static rtems_status_code mount_worker(
480  rtems_media_state state,
481  const char *src,
482  char **dest,
483  void *worker_arg
484)
485{
486  int rv = 0;
487
488  if (state == RTEMS_MEDIA_STATE_READY) {
489    rtems_dosfs_mount_options mount_options;
490    char *mount_path = NULL;
491
492    if (worker_arg == NULL) {
493      mount_path = rtems_media_replace_prefix(RTEMS_MEDIA_MOUNT_BASE, src);
494    } else {
495      mount_path = strdup(worker_arg);
496    }
497
498    if (mount_path == NULL) {
499      return RTEMS_IO_ERROR;
500    }
501
502    rv = rtems_mkdir(mount_path, S_IRWXU | S_IRWXG | S_IRWXO);
503    if (rv != 0) {
504      free(mount_path);
505
506      return RTEMS_IO_ERROR;
507    }
508
509    memset(&mount_options, 0, sizeof(mount_options));
510
511    /* In case this fails, we fall back to use the default converter */
512    mount_options.converter = rtems_dosfs_create_utf8_converter("CP850");
513
514    rv = mount(
515      src,
516      mount_path,
517      RTEMS_FILESYSTEM_TYPE_DOSFS,
518      RTEMS_FILESYSTEM_READ_WRITE,
519      &mount_options
520    );
521    if (rv != 0) {
522      (void) rmdir(mount_path);
523      free(mount_path);
524      (*mount_options.converter->handler->destroy)(mount_options.converter);
525
526      return RTEMS_IO_ERROR;
527    }
528
529    *dest = mount_path;
530  }
531
532  return RTEMS_SUCCESSFUL;
533}
534
535static rtems_status_code do_mount(
536  const char *src,
537  char **dest_ptr,
538  rtems_media_worker worker,
539  void *worker_arg
540)
541{
542  if (worker == NULL) {
543    worker = mount_worker;
544  }
545
546  return process_event(
547    RTEMS_MEDIA_EVENT_MOUNT,
548    src,
549    dest_ptr,
550    worker,
551    worker_arg
552  );
553}
554
555static rtems_status_code do_partition_attach(
556  const char *src,
557  char **dest_ptr,
558  rtems_media_worker worker,
559  void *worker_arg
560)
561{
562  rtems_status_code sc = RTEMS_SUCCESSFUL;
563  char *part_path = NULL;
564
565  if (worker != NULL) {
566    sc = process_event(
567      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
568      src,
569      &part_path,
570      worker,
571      worker_arg
572    );
573
574    if (sc == RTEMS_SUCCESSFUL) {
575      sc = do_mount(part_path, NULL, NULL, NULL);
576    }
577  } else {
578    sc = RTEMS_INVALID_ADDRESS;
579  }
580
581  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
582    *dest_ptr = part_path;
583  } else {
584    free(part_path);
585  }
586
587  return sc;
588}
589
590static rtems_status_code partition_attach_worker(
591  rtems_media_state state,
592  const char *src,
593  char **dest,
594  void *worker_arg
595)
596{
597  rtems_status_code sc = RTEMS_SUCCESSFUL;
598
599  if (state == RTEMS_MEDIA_STATE_READY) {
600    partition *part = worker_arg;
601    char *part_path = rtems_media_append_minor(src, part->index);
602
603    if (part_path == NULL) {
604      return RTEMS_IO_ERROR;
605    }
606
607    sc = rtems_blkdev_create_partition(
608      part_path,
609      src,
610      part->begin,
611      part->count
612    );
613    if (sc != RTEMS_SUCCESSFUL) {
614      free(part_path);
615
616      return RTEMS_IO_ERROR;
617    }
618
619    *dest = part_path;
620  }
621
622  return RTEMS_SUCCESSFUL;
623}
624
625static rtems_status_code attach_and_mount_partitions(
626  const char *disk_path,
627  const rtems_bdpart_partition *partitions,
628  size_t count
629)
630{
631  rtems_status_code sc = RTEMS_SUCCESSFUL;
632  size_t i = 0;
633
634  for (i = 0; i < count; ++i) {
635    partition part_desc = {
636      .index = i,
637      .begin = partitions [i].begin,
638      .count = partitions [i].end - partitions [i].begin
639    };
640    char *part_path = NULL;
641
642    sc = process_event(
643      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
644      disk_path,
645      &part_path,
646      partition_attach_worker,
647      &part_desc
648    );
649
650    if (sc == RTEMS_SUCCESSFUL) {
651      sc = do_mount(part_path, NULL, NULL, NULL);
652    }
653
654    free(part_path);
655  }
656
657  return sc;
658}
659
660static rtems_status_code partition_inquiry_worker(
661  rtems_media_state state,
662  const char *src,
663  char **dest RTEMS_UNUSED,
664  void *worker_arg
665)
666{
667  rtems_status_code sc = RTEMS_SUCCESSFUL;
668
669  if (state == RTEMS_MEDIA_STATE_READY) {
670    partition_table *pt = worker_arg;
671    rtems_bdpart_format format;
672
673    sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count);
674    if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) {
675      return RTEMS_IO_ERROR;
676    }
677  }
678
679  return RTEMS_SUCCESSFUL;
680}
681
682static rtems_status_code do_partition_inquiry(
683  const char *src,
684  char **dest_ptr,
685  rtems_media_worker worker,
686  void *worker_arg
687)
688{
689  rtems_status_code sc = RTEMS_SUCCESSFUL;
690
691  if (worker == NULL) {
692    rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT];
693    size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
694    partition_table pt = {
695     .partitions = partitions,
696     .count = &count
697    };
698
699    sc = process_event(
700      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
701      src,
702      dest_ptr,
703      partition_inquiry_worker,
704      &pt
705    );
706
707    if (sc == RTEMS_SUCCESSFUL) {
708      sc = attach_and_mount_partitions(src, partitions, count);
709    }
710  } else {
711    sc = process_event(
712      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
713      src,
714      dest_ptr,
715      worker,
716      worker_arg
717    );
718  }
719
720  return sc;
721}
722
723static rtems_status_code do_disk_attach(
724  const char *src,
725  char **dest_ptr,
726  rtems_media_worker worker,
727  void *worker_arg
728)
729{
730  rtems_status_code sc = RTEMS_SUCCESSFUL;
731  rtems_status_code rsc = RTEMS_SUCCESSFUL;
732  char *disk_path = NULL;
733
734  if (worker != NULL) {
735    rsc = process_event(
736      RTEMS_MEDIA_EVENT_DISK_ATTACH,
737      src,
738      &disk_path,
739      worker,
740      worker_arg
741    );
742   
743    if (rsc == RTEMS_SUCCESSFUL) {
744      sc = do_mount(disk_path, NULL, NULL, NULL);
745
746      if (sc != RTEMS_SUCCESSFUL) {
747        do_partition_inquiry(disk_path, NULL, NULL, NULL);
748      }
749    }
750  } else {
751    rsc = RTEMS_INVALID_ADDRESS;
752  }
753
754  if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) {
755    *dest_ptr = disk_path;
756  } else {
757    free(disk_path);
758  }
759
760  return rsc;
761}
762
763static rtems_status_code unmount_worker(
764  rtems_media_state state,
765  const char *src,
766  char **dest RTEMS_UNUSED,
767  void *worker_arg RTEMS_UNUSED
768)
769{
770  rtems_status_code sc = RTEMS_SUCCESSFUL;
771
772  if (state == RTEMS_MEDIA_STATE_READY) {
773    int rv = unmount(src);
774
775    if (rv == 0) {
776      rv = rmdir(src);
777      if (rv != 0) {
778        sc = RTEMS_IO_ERROR;
779      }
780    } else {
781      sc = RTEMS_IO_ERROR;
782    }
783  }
784
785  return sc;
786}
787
788static rtems_status_code do_unmount(
789  const char *src,
790  char **dest_ptr,
791  rtems_media_worker worker,
792  void *worker_arg
793)
794{
795  if (worker == NULL) {
796    worker = unmount_worker;
797    worker_arg = NULL;
798  }
799
800  return process_event(
801    RTEMS_MEDIA_EVENT_UNMOUNT,
802    src,
803    dest_ptr,
804    worker,
805    worker_arg
806  );
807}
808
809static rtems_status_code disk_detach_worker(
810  rtems_media_state state,
811  const char *src,
812  char **dest RTEMS_UNUSED,
813  void *worker_arg RTEMS_UNUSED
814)
815{
816  rtems_status_code rsc = RTEMS_SUCCESSFUL;
817
818  if (state == RTEMS_MEDIA_STATE_READY) {
819    int rv = unlink(src);
820
821    if (rv != 0) {
822      rsc = RTEMS_IO_ERROR;
823    }
824  }
825
826  return rsc;
827}
828
829static rtems_status_code detach_item(rtems_media_event event, media_item *item)
830{
831  rtems_status_code sc = RTEMS_SUCCESSFUL;
832  rtems_status_code rsc = RTEMS_SUCCESSFUL;
833
834  if (item->mount_path != NULL) {
835    sc = do_unmount(item->mount_path, NULL, NULL, NULL);
836    if (sc != RTEMS_SUCCESSFUL) {
837      rsc = RTEMS_IO_ERROR;
838    }
839  }
840
841  sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL);
842  if (sc != RTEMS_SUCCESSFUL) {
843    rsc = RTEMS_IO_ERROR;
844  }
845
846  return rsc;
847}
848
849static rtems_status_code detach_parent_item(media_item *parent)
850{
851  rtems_status_code sc = RTEMS_SUCCESSFUL;
852  rtems_status_code rsc = RTEMS_SUCCESSFUL;
853
854  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
855
856  while (!rtems_chain_is_tail(&media_item_chain, node)) {
857    media_item *child = (media_item *) node;
858
859    node = rtems_chain_next(node);
860
861    if (child->parent == parent) {
862      sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child);
863      if (sc != RTEMS_SUCCESSFUL) {
864        rsc = RTEMS_IO_ERROR;
865      }
866    }
867  }
868
869  sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent);
870  if (sc != RTEMS_SUCCESSFUL) {
871    rsc = RTEMS_IO_ERROR;
872  }
873
874  return rsc;
875}
876
877static rtems_status_code do_disk_detach(
878  const char *src,
879  char **dest_ptr,
880  rtems_media_worker worker,
881  void *worker_arg
882)
883{
884  if (worker == NULL) {
885    media_item *parent = get_media_item(src, NULL);
886
887    if (parent != NULL) {
888      return detach_parent_item(parent);
889    }
890
891    worker = disk_detach_worker;
892    worker_arg = NULL;
893  }
894
895  return process_event(
896    RTEMS_MEDIA_EVENT_DISK_DETACH,
897    src,
898    dest_ptr,
899    worker,
900    worker_arg
901  );
902}
903
904static rtems_status_code do_partition_detach(
905  const char *src,
906  char **dest_ptr,
907  rtems_media_worker worker,
908  void *worker_arg
909)
910{
911  if (worker == NULL) {
912    media_item *item = get_media_item(src, NULL);
913
914    if (item != NULL) {
915      return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item);
916    }
917
918    worker = disk_detach_worker;
919    worker_arg = NULL;
920  }
921
922  return process_event(
923    RTEMS_MEDIA_EVENT_PARTITION_DETACH,
924    src,
925    dest_ptr,
926    worker,
927    worker_arg
928  );
929}
930
931rtems_status_code rtems_media_post_event(
932  rtems_media_event event,
933  const char *src,
934  char **dest_ptr,
935  rtems_media_worker worker,
936  void *worker_arg
937)
938{
939  rtems_status_code sc = RTEMS_SUCCESSFUL;
940
941  lock();
942
943  switch (event) {
944    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
945      sc = do_disk_attach(src, dest_ptr, worker, worker_arg);
946      break;
947    case RTEMS_MEDIA_EVENT_DISK_DETACH:
948      sc = do_disk_detach(src, dest_ptr, worker, worker_arg);
949      break;
950    case RTEMS_MEDIA_EVENT_MOUNT:
951      sc = do_mount(src, dest_ptr, worker, worker_arg);
952      break;
953    case RTEMS_MEDIA_EVENT_UNMOUNT:
954      sc = do_unmount(src, dest_ptr, worker, worker_arg);
955      break;
956    case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY:
957      sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg);
958      break;
959    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
960      sc = do_partition_attach(src, dest_ptr, worker, worker_arg);
961      break;
962    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
963      sc = do_partition_detach(src, dest_ptr, worker, worker_arg);
964      break;
965    default:
966      sc = RTEMS_INVALID_ID;
967      break;
968  }
969
970  unlock();
971
972  return sc;
973}
Note: See TracBrowser for help on using the repository browser.