source: mainline/uspace/srv/volsrv/part.c

Last change on this file was 4285f384, checked in by Jiri Svoboda <jiri@…>, 5 months ago

Allow physically ejecting CD-ROM using vol eject -s

  • Property mode set to 100644
File size: 19.6 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup volsrv
30 * @{
31 */
32/**
33 * @file Partition handling
34 * @brief
35 */
36
37#include <adt/list.h>
38#include <bd.h>
39#include <errno.h>
40#include <fibril_synch.h>
41#include <io/log.h>
42#include <loc.h>
43#include <stdbool.h>
44#include <stdlib.h>
45#include <str.h>
46#include <str_error.h>
47#include <vfs/vfs.h>
48#include <vol.h>
49
50#include "empty.h"
51#include "mkfs.h"
52#include "part.h"
53#include "types/part.h"
54#include "volume.h"
55#include "volsrv.h"
56
57static errno_t vol_part_add_locked(vol_parts_t *, service_id_t);
58static void vol_part_remove_locked(vol_part_t *);
59static errno_t vol_part_find_by_id_ref_locked(vol_parts_t *, service_id_t,
60 vol_part_t **);
61
62struct fsname_type {
63 const char *name;
64 vol_fstype_t fstype;
65};
66
67static struct fsname_type fstab[] = {
68 { "ext4fs", fs_ext4 },
69 { "cdfs", fs_cdfs },
70 { "exfat", fs_exfat },
71 { "fat", fs_fat },
72 { "mfs", fs_minix },
73 { NULL, 0 }
74};
75
76static const char *fstype_str(vol_fstype_t fstype)
77{
78 struct fsname_type *fst;
79
80 fst = &fstab[0];
81 while (fst->name != NULL) {
82 if (fst->fstype == fstype)
83 return fst->name;
84 ++fst;
85 }
86
87 assert(false);
88 return NULL;
89}
90
91/** Check for new and removed partitions */
92static errno_t vol_part_check_new(vol_parts_t *parts)
93{
94 bool already_known;
95 bool still_exists;
96 category_id_t part_cat;
97 service_id_t *svcs;
98 size_t count, i;
99 link_t *cur, *next;
100 vol_part_t *part;
101 errno_t rc;
102
103 fibril_mutex_lock(&parts->lock);
104
105 rc = loc_category_get_id("partition", &part_cat, IPC_FLAG_BLOCKING);
106 if (rc != EOK) {
107 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'partition'.");
108 fibril_mutex_unlock(&parts->lock);
109 return ENOENT;
110 }
111
112 rc = loc_category_get_svcs(part_cat, &svcs, &count);
113 if (rc != EOK) {
114 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of partition "
115 "devices.");
116 fibril_mutex_unlock(&parts->lock);
117 return EIO;
118 }
119
120 /* Check for new partitions */
121 for (i = 0; i < count; i++) {
122 already_known = false;
123
124 // XXX Make this faster
125 list_foreach(parts->parts, lparts, vol_part_t, part) {
126 if (part->svc_id == svcs[i]) {
127 already_known = true;
128 break;
129 }
130 }
131
132 if (!already_known) {
133 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found partition '%lu'",
134 (unsigned long) svcs[i]);
135 rc = vol_part_add_locked(parts, svcs[i]);
136 if (rc != EOK) {
137 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not add "
138 "partition.");
139 }
140 }
141 }
142
143 /* Check for removed partitions */
144 cur = list_first(&parts->parts);
145 while (cur != NULL) {
146 next = list_next(cur, &parts->parts);
147 part = list_get_instance(cur, vol_part_t, lparts);
148
149 still_exists = false;
150 // XXX Make this faster
151 for (i = 0; i < count; i++) {
152 if (part->svc_id == svcs[i]) {
153 still_exists = true;
154 break;
155 }
156 }
157
158 if (!still_exists) {
159 log_msg(LOG_DEFAULT, LVL_DEBUG, "Partition '%zu' is gone",
160 part->svc_id);
161 vol_part_remove_locked(part);
162 }
163
164 cur = next;
165 }
166
167 free(svcs);
168
169 fibril_mutex_unlock(&parts->lock);
170 return EOK;
171}
172
173static vol_part_t *vol_part_new(void)
174{
175 vol_part_t *part = calloc(1, sizeof(vol_part_t));
176
177 if (part == NULL) {
178 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating partition "
179 "structure. Out of memory.");
180 return NULL;
181 }
182
183 refcount_init(&part->refcnt);
184 link_initialize(&part->lparts);
185 part->parts = NULL;
186 part->pcnt = vpc_empty;
187
188 return part;
189}
190
191static void vol_part_delete(vol_part_t *part)
192{
193 log_msg(LOG_DEFAULT, LVL_ERROR, "Freeing partition %p", part);
194 if (part == NULL)
195 return;
196
197 if (part->volume != NULL)
198 vol_volume_del_ref(part->volume);
199
200 free(part->cur_mp);
201 free(part->svc_name);
202 free(part);
203}
204
205static errno_t vol_part_probe(vol_part_t *part)
206{
207 bool empty;
208 vfs_fs_probe_info_t info;
209 struct fsname_type *fst;
210 char *label;
211 vol_volume_t *volume;
212 errno_t rc;
213
214 log_msg(LOG_DEFAULT, LVL_DEBUG, "Probe partition %s", part->svc_name);
215
216 assert(fibril_mutex_is_locked(&part->parts->lock));
217
218 fst = &fstab[0];
219 while (fst->name != NULL) {
220 rc = vfs_fsprobe(fst->name, part->svc_id, &info);
221 if (rc == EOK)
222 break;
223 ++fst;
224 }
225
226 if (fst->name != NULL) {
227 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found %s, label '%s'",
228 fst->name, info.label);
229 label = str_dup(info.label);
230 if (label == NULL) {
231 rc = ENOMEM;
232 goto error;
233 }
234
235 part->pcnt = vpc_fs;
236 part->fstype = fst->fstype;
237 part->label = label;
238 } else {
239 log_msg(LOG_DEFAULT, LVL_NOTE, "Partition does not contain "
240 "a recognized file system.");
241
242 rc = volsrv_part_is_empty(part->svc_id, &empty);
243 if (rc != EOK) {
244 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determining if "
245 "partition is empty.");
246 rc = EIO;
247 goto error;
248 }
249
250 label = str_dup("");
251 if (label == NULL) {
252 rc = ENOMEM;
253 goto error;
254 }
255
256 part->pcnt = empty ? vpc_empty : vpc_unknown;
257 part->label = label;
258 }
259
260 /* Look up new or existing volume. */
261 rc = vol_volume_lookup_ref(part->parts->volumes, part->label, &volume);
262 if (rc != EOK)
263 goto error;
264
265 part->volume = volume;
266 return EOK;
267
268error:
269 return rc;
270}
271
272/** Determine if partition is allowed to be mounted by default.
273 *
274 * @param part Partition
275 * @return @c true iff partition is allowed to be mounted by default
276 */
277static bool vol_part_allow_mount_by_def(vol_part_t *part)
278{
279 /* CDFS is safe to mount (after all, it is read-only) */
280 if (part->pcnt == vpc_fs && part->fstype == fs_cdfs)
281 return true;
282
283 /* For other file systems disallow mounting from ATA hard drive */
284 if (str_str(part->svc_name, "\\ata-c") != NULL)
285 return false;
286
287 /* Allow otherwise (e.g. USB mass storage) */
288 return true;
289}
290
291/** Determine the default mount point for a partition.
292 *
293 * @param part Partition
294 * @return Pointer to the constant string "Auto" or "None"
295 */
296static const char *vol_part_def_mountp(vol_part_t *part)
297{
298 return vol_part_allow_mount_by_def(part) ? "Auto" : "None";
299}
300
301/** Determine actual mount path to be used for a partition.
302 *
303 * @param part Partition
304 * @param rpath Place to store pointer to newly allocated string or @c NULL
305 * if volume should not be mounted
306 * @param rauto Place to store boolean flag whether mount point is automatic
307 *
308 * @return EOK on success, ENOMEM if out of memory
309 */
310static errno_t vol_part_determine_mount_path(vol_part_t *part, char **rpath,
311 bool *rauto)
312{
313 const char *cfg_mp;
314 char *mp;
315 bool mp_auto;
316 int err;
317
318 /* Get configured mount point */
319 if (str_size(part->volume->mountp) > 0) {
320 cfg_mp = part->volume->mountp;
321 log_msg(LOG_DEFAULT, LVL_DEBUG, "Configured mount point '%s'",
322 cfg_mp);
323 } else {
324 cfg_mp = vol_part_def_mountp(part);
325 log_msg(LOG_DEFAULT, LVL_DEBUG, "Default mount point '%s'",
326 cfg_mp);
327 }
328
329 if (str_cmp(cfg_mp, "Auto") == 0 || str_cmp(cfg_mp, "auto") == 0) {
330
331 if (str_size(part->label) < 1) {
332 /* Don't mount nameless volumes */
333 *rpath = NULL;
334 *rauto = false;
335 return EOK;
336 }
337
338 log_msg(LOG_DEFAULT, LVL_DEBUG, "Determine MP label='%s'", part->label);
339 err = asprintf(&mp, "/vol/%s", part->label);
340 if (err < 0) {
341 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory");
342 return ENOMEM;
343 }
344
345 mp_auto = true;
346 } else if (str_cmp(cfg_mp, "None") == 0 || str_cmp(cfg_mp, "none") == 0) {
347 mp = NULL;
348 mp_auto = false;
349 } else {
350 mp = str_dup(cfg_mp);
351 mp_auto = false;
352 }
353
354 *rpath = mp;
355 *rauto = mp_auto;
356 return EOK;
357}
358
359/** Mount partition.
360 *
361 * @param part Partition
362 */
363static errno_t vol_part_mount(vol_part_t *part)
364{
365 char *mp;
366 bool mp_auto;
367 errno_t rc;
368
369 rc = vol_part_determine_mount_path(part, &mp, &mp_auto);
370 if (rc != EOK) {
371 log_msg(LOG_DEFAULT, LVL_ERROR, "Error determining mount point.\n");
372 return rc;
373 }
374
375 if (mp == NULL) {
376 log_msg(LOG_DEFAULT, LVL_NOTE, "Not mounting volume.");
377 return EOK;
378 }
379
380 if (mp_auto) {
381 /* Create directory for automatic mount point */
382 log_msg(LOG_DEFAULT, LVL_DEBUG, "Create mount point '%s'", mp);
383 rc = vfs_link_path(mp, KIND_DIRECTORY, NULL);
384 if (rc != EOK) {
385 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating mount point '%s'",
386 mp);
387 free(mp);
388 return EIO;
389 }
390 }
391
392 log_msg(LOG_DEFAULT, LVL_DEBUG, "Call vfs_mount_path mp='%s' fstype='%s' svc_name='%s'",
393 mp, fstype_str(part->fstype), part->svc_name);
394 rc = vfs_mount_path(mp, fstype_str(part->fstype),
395 part->svc_name, "", 0, 0);
396 if (rc != EOK) {
397 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed mounting %s at %s to %s",
398 fstype_str(part->fstype), part->svc_name, mp);
399 } else {
400 log_msg(LOG_DEFAULT, LVL_NOTE, "Mounted %s at %s to %s\n",
401 fstype_str(part->fstype), part->svc_name, mp);
402 }
403
404 part->cur_mp = mp;
405 part->cur_mp_auto = mp_auto;
406
407 if (str_cmp(mp, "/w") == 0) {
408 log_msg(LOG_DEFAULT, LVL_NOTE, "Mounted system volume - "
409 "loading additional configuration.");
410 rc = vol_volumes_merge_to(part->parts->volumes,
411 vol_cfg_file);
412 if (rc != EOK) {
413 log_msg(LOG_DEFAULT, LVL_ERROR, "Error loading "
414 "additional configuration.");
415 return rc;
416 }
417 }
418
419 return rc;
420}
421
422static errno_t vol_part_add_locked(vol_parts_t *parts, service_id_t sid)
423{
424 vol_part_t *part;
425 errno_t rc;
426
427 assert(fibril_mutex_is_locked(&parts->lock));
428 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_add_locked(%zu)", sid);
429
430 /* Check for duplicates */
431 rc = vol_part_find_by_id_ref_locked(parts, sid, &part);
432 if (rc == EOK) {
433 vol_part_del_ref(part);
434 return EEXIST;
435 }
436
437 log_msg(LOG_DEFAULT, LVL_DEBUG, "partition %zu is new", sid);
438
439 part = vol_part_new();
440 if (part == NULL)
441 return ENOMEM;
442
443 part->svc_id = sid;
444 part->parts = parts;
445
446 rc = loc_service_get_name(sid, &part->svc_name);
447 if (rc != EOK) {
448 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
449 goto error;
450 }
451
452 rc = vol_part_probe(part);
453 if (rc != EOK)
454 goto error;
455
456 rc = vol_part_mount(part);
457 if (rc != EOK)
458 goto error;
459
460 list_append(&part->lparts, &parts->parts);
461
462 log_msg(LOG_DEFAULT, LVL_DEBUG, "Added partition %zu", part->svc_id);
463
464 return EOK;
465
466error:
467 vol_part_delete(part);
468 return rc;
469}
470
471static void vol_part_remove_locked(vol_part_t *part)
472{
473 assert(fibril_mutex_is_locked(&part->parts->lock));
474 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_remove_locked(%zu)",
475 part->svc_id);
476
477 list_remove(&part->lparts);
478
479 log_msg(LOG_DEFAULT, LVL_DEBUG, "Removed partition.");
480 vol_part_del_ref(part);
481}
482
483errno_t vol_part_add_part(vol_parts_t *parts, service_id_t sid)
484{
485 errno_t rc;
486
487 fibril_mutex_lock(&parts->lock);
488 rc = vol_part_add_locked(parts, sid);
489 fibril_mutex_unlock(&parts->lock);
490
491 return rc;
492}
493
494static void vol_part_cat_change_cb(void *arg)
495{
496 vol_parts_t *parts = (vol_parts_t *) arg;
497
498 (void) vol_part_check_new(parts);
499}
500
501errno_t vol_parts_create(vol_volumes_t *volumes, vol_parts_t **rparts)
502{
503 vol_parts_t *parts;
504
505 parts = calloc(1, sizeof(vol_parts_t));
506 if (parts == NULL)
507 return ENOMEM;
508
509 fibril_mutex_initialize(&parts->lock);
510 list_initialize(&parts->parts);
511 parts->volumes = volumes;
512
513 *rparts = parts;
514 return EOK;
515}
516
517void vol_parts_destroy(vol_parts_t *parts)
518{
519 if (parts == NULL)
520 return;
521
522 assert(list_empty(&parts->parts));
523 free(parts);
524}
525
526errno_t vol_part_discovery_start(vol_parts_t *parts)
527{
528 errno_t rc;
529
530 rc = loc_register_cat_change_cb(vol_part_cat_change_cb, parts);
531 if (rc != EOK) {
532 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
533 "for partition discovery: %s.", str_error(rc));
534 return rc;
535 }
536
537 return vol_part_check_new(parts);
538}
539
540/** Get list of partitions as array of service IDs. */
541errno_t vol_part_get_ids(vol_parts_t *parts, service_id_t *id_buf,
542 size_t buf_size, size_t *act_size)
543{
544 size_t act_cnt;
545 size_t buf_cnt;
546
547 fibril_mutex_lock(&parts->lock);
548
549 buf_cnt = buf_size / sizeof(service_id_t);
550
551 act_cnt = list_count(&parts->parts);
552 *act_size = act_cnt * sizeof(service_id_t);
553
554 if (buf_size % sizeof(service_id_t) != 0) {
555 fibril_mutex_unlock(&parts->lock);
556 return EINVAL;
557 }
558
559 size_t pos = 0;
560 list_foreach(parts->parts, lparts, vol_part_t, part) {
561 if (pos < buf_cnt)
562 id_buf[pos] = part->svc_id;
563 pos++;
564 }
565
566 fibril_mutex_unlock(&parts->lock);
567 return EOK;
568}
569
570static errno_t vol_part_find_by_id_ref_locked(vol_parts_t *parts,
571 service_id_t sid, vol_part_t **rpart)
572{
573 assert(fibril_mutex_is_locked(&parts->lock));
574
575 list_foreach(parts->parts, lparts, vol_part_t, part) {
576 if (part->svc_id == sid) {
577 /* Add reference */
578 refcount_up(&part->refcnt);
579 *rpart = part;
580 return EOK;
581 }
582 }
583
584 return ENOENT;
585}
586
587errno_t vol_part_find_by_id_ref(vol_parts_t *parts, service_id_t sid,
588 vol_part_t **rpart)
589{
590 errno_t rc;
591
592 fibril_mutex_lock(&parts->lock);
593 rc = vol_part_find_by_id_ref_locked(parts, sid, rpart);
594 fibril_mutex_unlock(&parts->lock);
595
596 return rc;
597}
598
599/** Find partition by filesystem path.
600 *
601 * @param parts Partitions
602 * @param path Filesystem path
603 * @param rpart Place to store pointer to partition
604 * @return EOK on success, ENOENT if not found, ENOMEM if out of memory
605 */
606errno_t vol_part_find_by_path_ref(vol_parts_t *parts, const char *path,
607 vol_part_t **rpart)
608{
609 errno_t rc;
610 char *mpath;
611 bool mauto;
612
613 fibril_mutex_lock(&parts->lock);
614
615 list_foreach(parts->parts, lparts, vol_part_t, part) {
616 rc = vol_part_determine_mount_path(part, &mpath, &mauto);
617 if (rc != EOK) {
618 fibril_mutex_unlock(&parts->lock);
619 return ENOMEM;
620 }
621
622 if (mpath != NULL && str_cmp(mpath, path) == 0) {
623 /* Add reference */
624 refcount_up(&part->refcnt);
625 fibril_mutex_unlock(&parts->lock);
626 free(mpath);
627 *rpart = part;
628 return EOK;
629 }
630
631 if (mpath != NULL)
632 free(mpath);
633 }
634
635 fibril_mutex_unlock(&parts->lock);
636 return ENOENT;
637}
638
639void vol_part_del_ref(vol_part_t *part)
640{
641 if (refcount_down(&part->refcnt))
642 vol_part_delete(part);
643}
644
645static errno_t vol_part_eject_device(service_id_t svcid)
646{
647 async_sess_t *sess;
648 errno_t rc;
649 bd_t *bd;
650
651 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_eject_device(%zu)",
652 (size_t)svcid);
653
654 sess = loc_service_connect(svcid, INTERFACE_BLOCK, 0);
655 if (sess == NULL)
656 return EIO;
657
658 rc = bd_open(sess, &bd);
659 if (rc != EOK) {
660 async_hangup(sess);
661 return EIO;
662 }
663
664 rc = bd_eject(bd);
665 if (rc != EOK) {
666 log_msg(LOG_DEFAULT, LVL_WARN, "vol_part_eject_device(): "
667 "eject fail");
668 bd_close(bd);
669 async_hangup(sess);
670 return EIO;
671 }
672
673 bd_close(bd);
674 async_hangup(sess);
675 return EOK;
676}
677
678errno_t vol_part_eject_part(vol_part_t *part, vol_eject_flags_t flags)
679{
680 int rc;
681
682 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_eject_part()");
683
684 if (part->cur_mp == NULL) {
685 /* Partition is not mounted, nothing to do. */
686 log_msg(LOG_DEFAULT, LVL_DEBUG, "Partition not mounted, "
687 "nothing to do.");
688 goto done;
689 }
690
691 rc = vfs_unmount_path(part->cur_mp);
692 if (rc != EOK) {
693 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unmounting partition "
694 "from %s", part->cur_mp);
695 return rc;
696 }
697
698 if (part->cur_mp_auto) {
699 rc = vfs_unlink_path(part->cur_mp);
700 if (rc != EOK) {
701 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting "
702 "mount directory %s.", part->cur_mp);
703 }
704 }
705
706 if ((flags & vef_physical) != 0) {
707 rc = vol_part_eject_device(part->svc_id);
708 if (rc != EOK) {
709 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed physically "
710 "ejecting device %s.", part->svc_name);
711 }
712 }
713
714 free(part->cur_mp);
715 part->cur_mp = NULL;
716 part->cur_mp_auto = false;
717done:
718 return EOK;
719}
720
721errno_t vol_part_empty_part(vol_part_t *part)
722{
723 errno_t rc;
724
725 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part()");
726
727 rc = volsrv_part_empty(part->svc_id);
728 if (rc != EOK) {
729 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_empty_part() - failed %s",
730 str_error(rc));
731 return rc;
732 }
733
734 part->pcnt = vpc_empty;
735 return EOK;
736}
737
738/** Insert volume.
739 *
740 * Re-mount the volume in the partition, if applicable.
741 *
742 * @param part Partition
743 */
744errno_t vol_part_insert_part(vol_part_t *part)
745{
746 int rc;
747
748 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_insert_part()");
749
750 fibril_mutex_lock(&part->parts->lock);
751
752 if (part->cur_mp != NULL) {
753 fibril_mutex_unlock(&part->parts->lock);
754 return EOK;
755 }
756
757 rc = vol_part_probe(part);
758 if (rc != EOK)
759 goto error;
760
761 rc = vol_part_mount(part);
762 if (rc != EOK)
763 goto error;
764
765 fibril_mutex_unlock(&part->parts->lock);
766
767 return EOK;
768error:
769 return rc;
770}
771
772/** Set mount point.
773 *
774 * Verify and set a mount point. If the value of the mount point is
775 * the same as the default value, we will actually unset the mount point
776 * value (therefore effectively changing it to use the default).
777 *
778 * @return EOK on success, error code otherwise
779 */
780static errno_t vol_part_mountp_set(vol_part_t *part, const char *mountp)
781{
782 errno_t rc;
783 const char *def_mp;
784 const char *mp;
785
786 rc = vol_mountp_validate(mountp);
787 if (rc != EOK)
788 return rc;
789
790 def_mp = vol_part_def_mountp(part);
791
792 /* If the value is the same as default, set to empty string. */
793 if (str_cmp(def_mp, mountp) == 0)
794 mp = "";
795 else
796 mp = mountp;
797
798 rc = vol_volume_set_mountp(part->volume, mp);
799 if (rc != EOK)
800 return rc;
801
802 return EOK;
803}
804
805errno_t vol_part_mkfs_part(vol_part_t *part, vol_fstype_t fstype,
806 const char *label, const char *mountp)
807{
808 errno_t rc;
809
810 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part()");
811
812 fibril_mutex_lock(&part->parts->lock);
813
814 rc = volsrv_part_mkfs(part->svc_id, fstype, label);
815 if (rc != EOK) {
816 log_msg(LOG_DEFAULT, LVL_DEBUG, "vol_part_mkfs_part() - failed %s",
817 str_error(rc));
818 fibril_mutex_unlock(&part->parts->lock);
819 return rc;
820 }
821
822 /*
823 * Re-probe the partition to update information. This is needed since
824 * the FS can make conversions of the volume label (e.g. make it
825 * uppercase).
826 */
827 rc = vol_part_probe(part);
828 if (rc != EOK) {
829 fibril_mutex_unlock(&part->parts->lock);
830 return rc;
831 }
832
833 rc = vol_part_mountp_set(part, mountp);
834 if (rc != EOK) {
835 fibril_mutex_unlock(&part->parts->lock);
836 return rc;
837 }
838
839 rc = vol_part_mount(part);
840 if (rc != EOK) {
841 fibril_mutex_unlock(&part->parts->lock);
842 return rc;
843 }
844
845 fibril_mutex_unlock(&part->parts->lock);
846 return EOK;
847}
848
849/** Set partition mount point.
850 *
851 * Set the partition mount point, (un-, re-)mounting the partition as necessary.
852 *
853 * @param part Partition
854 * @param mountp
855 *
856 * @return EOK on success or error code
857 */
858errno_t vol_part_set_mountp_part(vol_part_t *part, const char *mountp)
859{
860 errno_t rc;
861
862 if (part->cur_mp != NULL) {
863 rc = vol_part_eject_part(part, vef_none);
864 if (rc != EOK)
865 return rc;
866 }
867
868 rc = vol_part_mountp_set(part, mountp);
869 if (rc != EOK)
870 return rc;
871
872 rc = vol_part_mount(part);
873 if (rc != EOK)
874 return rc;
875
876 return EOK;
877}
878
879errno_t vol_part_get_info(vol_part_t *part, vol_part_info_t *pinfo)
880{
881 memset(pinfo, 0, sizeof(*pinfo));
882
883 pinfo->pcnt = part->pcnt;
884 pinfo->fstype = part->fstype;
885 str_cpy(pinfo->label, sizeof(pinfo->label), part->label);
886 if (part->cur_mp != NULL)
887 str_cpy(pinfo->cur_mp, sizeof(pinfo->cur_mp), part->cur_mp);
888 pinfo->cur_mp_auto = part->cur_mp_auto;
889 return EOK;
890}
891
892/** @}
893 */
Note: See TracBrowser for help on using the repository browser.