103 zfs_close(zhp); |
109 zfs_close(zhp); |
104 |
110 |
105 return (0); |
111 return (0); |
106 } |
112 } |
107 |
113 |
108 void |
114 int |
109 zfs_add_sort_column(zfs_sort_column_t **sc, zfs_prop_t prop, |
115 zfs_add_sort_column(zfs_sort_column_t **sc, const char *name, |
110 boolean_t reverse) |
116 boolean_t reverse) |
111 { |
117 { |
112 zfs_sort_column_t *col; |
118 zfs_sort_column_t *col; |
|
119 zfs_prop_t prop; |
|
120 |
|
121 if ((prop = zfs_name_to_prop(name)) == ZFS_PROP_INVAL && |
|
122 !zfs_prop_user(name)) |
|
123 return (-1); |
113 |
124 |
114 col = safe_malloc(sizeof (zfs_sort_column_t)); |
125 col = safe_malloc(sizeof (zfs_sort_column_t)); |
115 |
126 |
116 col->sc_prop = prop; |
127 col->sc_prop = prop; |
117 col->sc_reverse = reverse; |
128 col->sc_reverse = reverse; |
118 col->sc_next = NULL; |
129 if (prop == ZFS_PROP_INVAL) { |
|
130 col->sc_user_prop = safe_malloc(strlen(name) + 1); |
|
131 (void) strcpy(col->sc_user_prop, name); |
|
132 } |
119 |
133 |
120 if (*sc == NULL) { |
134 if (*sc == NULL) { |
121 col->sc_last = col; |
135 col->sc_last = col; |
122 *sc = col; |
136 *sc = col; |
123 } else { |
137 } else { |
124 (*sc)->sc_last->sc_next = col; |
138 (*sc)->sc_last->sc_next = col; |
125 (*sc)->sc_last = col; |
139 (*sc)->sc_last = col; |
126 } |
140 } |
|
141 |
|
142 return (0); |
127 } |
143 } |
128 |
144 |
129 void |
145 void |
130 zfs_free_sort_columns(zfs_sort_column_t *sc) |
146 zfs_free_sort_columns(zfs_sort_column_t *sc) |
131 { |
147 { |
132 zfs_sort_column_t *col; |
148 zfs_sort_column_t *col; |
133 |
149 |
134 while (sc != NULL) { |
150 while (sc != NULL) { |
135 col = sc->sc_next; |
151 col = sc->sc_next; |
|
152 free(sc->sc_user_prop); |
136 free(sc); |
153 free(sc); |
137 sc = col; |
154 sc = col; |
138 } |
155 } |
139 } |
156 } |
140 |
157 |
212 zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle; |
229 zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle; |
213 zfs_sort_column_t *sc = (zfs_sort_column_t *)data; |
230 zfs_sort_column_t *sc = (zfs_sort_column_t *)data; |
214 zfs_sort_column_t *psc; |
231 zfs_sort_column_t *psc; |
215 |
232 |
216 for (psc = sc; psc != NULL; psc = psc->sc_next) { |
233 for (psc = sc; psc != NULL; psc = psc->sc_next) { |
217 char lstr[ZFS_MAXPROPLEN], rstr[ZFS_MAXPROPLEN]; |
234 char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN]; |
|
235 char *lstr, *rstr; |
218 uint64_t lnum, rnum; |
236 uint64_t lnum, rnum; |
219 int lvalid, rvalid; |
237 boolean_t lvalid, rvalid; |
220 int ret = 0; |
238 int ret = 0; |
221 |
239 |
222 if (zfs_prop_is_string(psc->sc_prop)) { |
240 /* |
223 lvalid = zfs_prop_get(l, psc->sc_prop, lstr, |
241 * We group the checks below the generic code. If 'lstr' and |
224 sizeof (lstr), NULL, NULL, 0, B_TRUE); |
242 * 'rstr' are non-NULL, then we do a string based comparison. |
225 rvalid = zfs_prop_get(r, psc->sc_prop, rstr, |
243 * Otherwise, we compare 'lnum' and 'rnum'. |
226 sizeof (rstr), NULL, NULL, 0, B_TRUE); |
244 */ |
227 |
245 lstr = rstr = NULL; |
228 if ((lvalid == -1) && (rvalid == -1)) |
246 if (psc->sc_prop == ZFS_PROP_INVAL) { |
229 continue; |
247 nvlist_t *luser, *ruser; |
230 if (lvalid == -1) |
248 nvlist_t *lval, *rval; |
231 return (1); |
249 |
232 else if (rvalid == -1) |
250 luser = zfs_get_user_props(l); |
233 return (-1); |
251 ruser = zfs_get_user_props(r); |
234 |
252 |
235 ret = strcmp(lstr, rstr); |
253 lvalid = (nvlist_lookup_nvlist(luser, |
|
254 psc->sc_user_prop, &lval) == 0); |
|
255 rvalid = (nvlist_lookup_nvlist(ruser, |
|
256 psc->sc_user_prop, &rval) == 0); |
|
257 |
|
258 if (lvalid) |
|
259 verify(nvlist_lookup_string(lval, |
|
260 ZFS_PROP_VALUE, &lstr) == 0); |
|
261 if (rvalid) |
|
262 verify(nvlist_lookup_string(rval, |
|
263 ZFS_PROP_VALUE, &rstr) == 0); |
|
264 |
|
265 } else if (zfs_prop_is_string(psc->sc_prop)) { |
|
266 lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf, |
|
267 sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0); |
|
268 rvalid = (zfs_prop_get(r, psc->sc_prop, rbuf, |
|
269 sizeof (rbuf), NULL, NULL, 0, B_TRUE) == 0); |
|
270 |
|
271 lstr = lbuf; |
|
272 rstr = rbuf; |
236 } else { |
273 } else { |
237 lvalid = zfs_prop_valid_for_type(psc->sc_prop, |
274 lvalid = zfs_prop_valid_for_type(psc->sc_prop, |
238 zfs_get_type(l)); |
275 zfs_get_type(l)); |
239 rvalid = zfs_prop_valid_for_type(psc->sc_prop, |
276 rvalid = zfs_prop_valid_for_type(psc->sc_prop, |
240 zfs_get_type(r)); |
277 zfs_get_type(r)); |
241 |
278 |
242 if (!lvalid && !rvalid) |
279 if (lvalid) |
243 continue; |
280 (void) zfs_prop_get_numeric(l, psc->sc_prop, |
244 else if (!lvalid) |
281 &lnum, NULL, NULL, 0); |
245 return (1); |
282 if (rvalid) |
246 else if (!rvalid) |
283 (void) zfs_prop_get_numeric(r, psc->sc_prop, |
247 return (-1); |
284 &rnum, NULL, NULL, 0); |
248 |
285 } |
249 (void) zfs_prop_get_numeric(l, psc->sc_prop, &lnum, |
286 |
250 NULL, NULL, 0); |
287 if (!lvalid && !rvalid) |
251 (void) zfs_prop_get_numeric(r, psc->sc_prop, &rnum, |
288 continue; |
252 NULL, NULL, 0); |
289 else if (!lvalid) |
253 |
290 return (1); |
254 if (lnum < rnum) |
291 else if (!rvalid) |
255 ret = -1; |
292 return (-1); |
256 else if (lnum > rnum) |
293 |
257 ret = 1; |
294 if (lstr) |
258 } |
295 ret = strcmp(lstr, rstr); |
|
296 if (lnum < rnum) |
|
297 ret = -1; |
|
298 else if (lnum > rnum) |
|
299 ret = 1; |
259 |
300 |
260 if (ret != 0) { |
301 if (ret != 0) { |
261 if (psc->sc_reverse == B_TRUE) |
302 if (psc->sc_reverse == B_TRUE) |
262 ret = (ret < 0) ? 1 : -1; |
303 ret = (ret < 0) ? 1 : -1; |
263 return (ret); |
304 return (ret); |