Tizen 2.1 base
[external/device-mapper.git] / lib / format_text / flags.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
4  *
5  * This file is part of LVM2.
6  *
7  * This copyrighted material is made available to anyone wishing to use,
8  * modify, copy, or redistribute it subject to the terms and conditions
9  * of the GNU Lesser General Public License v.2.1.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14  */
15
16 #include "lib.h"
17 #include "metadata.h"
18 #include "import-export.h"
19 #include "lvm-string.h"
20
21 /*
22  * Bitsets held in the 'status' flags get
23  * converted into arrays of strings.
24  */
25 struct flag {
26         const uint64_t mask;
27         const char *description;
28         int kind;
29 };
30
31 static const struct flag _vg_flags[] = {
32         {EXPORTED_VG, "EXPORTED", STATUS_FLAG},
33         {RESIZEABLE_VG, "RESIZEABLE", STATUS_FLAG},
34         {PVMOVE, "PVMOVE", STATUS_FLAG},
35         {LVM_READ, "READ", STATUS_FLAG},
36         {LVM_WRITE, "WRITE", STATUS_FLAG},
37         {CLUSTERED, "CLUSTERED", STATUS_FLAG},
38         {SHARED, "SHARED", STATUS_FLAG},
39         {PARTIAL_VG, NULL, 0},
40         {PRECOMMITTED, NULL, 0},
41         {0, NULL, 0}
42 };
43
44 static const struct flag _pv_flags[] = {
45         {ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
46         {EXPORTED_VG, "EXPORTED", STATUS_FLAG},
47         {MISSING_PV, "MISSING", COMPATIBLE_FLAG},
48         {0, NULL, 0}
49 };
50
51 static const struct flag _lv_flags[] = {
52         {LVM_READ, "READ", STATUS_FLAG},
53         {LVM_WRITE, "WRITE", STATUS_FLAG},
54         {FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
55         {VISIBLE_LV, "VISIBLE", STATUS_FLAG},
56         {PVMOVE, "PVMOVE", STATUS_FLAG},
57         {LOCKED, "LOCKED", STATUS_FLAG},
58         {MIRROR_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
59         {MIRROR_IMAGE, NULL, 0},
60         {MIRROR_LOG, NULL, 0},
61         {MIRRORED, NULL, 0},
62         {VIRTUAL, NULL, 0},
63         {SNAPSHOT, NULL, 0},
64         {MERGING, NULL, 0},
65         {ACTIVATE_EXCL, NULL, 0},
66         {CONVERTING, NULL, 0},
67         {PARTIAL_LV, NULL, 0},
68         {POSTORDER_FLAG, NULL, 0},
69         {VIRTUAL_ORIGIN, NULL, 0},
70         {REPLICATOR, NULL, 0},
71         {REPLICATOR_LOG, NULL, 0},
72         {0, NULL, 0}
73 };
74
75 static const struct flag *_get_flags(int type)
76 {
77         switch (type & ~STATUS_FLAG) {
78         case VG_FLAGS:
79                 return _vg_flags;
80
81         case PV_FLAGS:
82                 return _pv_flags;
83
84         case LV_FLAGS:
85                 return _lv_flags;
86         }
87
88         log_error("Unknown flag set requested.");
89         return NULL;
90 }
91
92 /*
93  * Converts a bitset to an array of string values,
94  * using one of the tables defined at the top of
95  * the file.
96  */
97 int print_flags(uint64_t status, int type, char *buffer, size_t size)
98 {
99         int f, first = 1;
100         const struct flag *flags;
101
102         if (!(flags = _get_flags(type)))
103                 return_0;
104
105         if (!emit_to_buffer(&buffer, &size, "["))
106                 return 0;
107
108         for (f = 0; flags[f].mask; f++) {
109                 if (status & flags[f].mask) {
110                         status &= ~flags[f].mask;
111
112                         if ((type & STATUS_FLAG) != flags[f].kind)
113                                 continue;
114
115                         /* Internal-only flag? */
116                         if (!flags[f].description)
117                                 continue;
118
119                         if (!first) {
120                                 if (!emit_to_buffer(&buffer, &size, ", "))
121                                         return 0;
122                         } else
123                                 first = 0;
124         
125                         if (!emit_to_buffer(&buffer, &size, "\"%s\"",
126                             flags[f].description))
127                                 return 0;
128                 }
129         }
130
131         if (!emit_to_buffer(&buffer, &size, "]"))
132                 return 0;
133
134         if (status)
135                 log_error("Metadata inconsistency: Not all flags successfully "
136                           "exported.");
137
138         return 1;
139 }
140
141 int read_flags(uint64_t *status, int type, const struct config_value *cv)
142 {
143         int f;
144         uint64_t s = UINT64_C(0);
145         const struct flag *flags;
146
147         if (!(flags = _get_flags(type)))
148                 return_0;
149
150         if (cv->type == CFG_EMPTY_ARRAY)
151                 goto out;
152
153         while (cv) {
154                 if (cv->type != CFG_STRING) {
155                         log_error("Status value is not a string.");
156                         return 0;
157                 }
158
159                 for (f = 0; flags[f].description; f++)
160                         if (!strcmp(flags[f].description, cv->v.str)) {
161                                 s |= flags[f].mask;
162                                 break;
163                         }
164
165                 if (type == VG_FLAGS && !strcmp(cv->v.str, "PARTIAL")) {
166                         /*
167                          * Exception: We no longer write this flag out, but it
168                          * might be encountered in old backup files, so restore
169                          * it in that case. It is never part of live metadata
170                          * though, so only vgcfgrestore needs to be concerned
171                          * by this case.
172                          */
173                         s |= PARTIAL_VG;
174                 } else if (!flags[f].description && (type & STATUS_FLAG)) {
175                         log_error("Unknown status flag '%s'.", cv->v.str);
176                         return 0;
177                 }
178
179                 cv = cv->next;
180         }
181
182       out:
183         *status |= s;
184         return 1;
185 }