~ubuntu-branches/debian/stretch/btrfs-tools/stretch

« back to all changes in this revision

Viewing changes to dir-item.c

  • Committer: Package Import Robot
  • Author(s): Dimitri John Ledkov
  • Date: 2014-10-23 22:04:07 UTC
  • mfrom: (1.2.15) (6.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20141023220407-skt9hy0ft4oim95o
Tags: 3.17-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Boston, MA 021110-1307, USA.
17
17
 */
18
18
 
 
19
#include <linux/limits.h>
19
20
#include "ctree.h"
20
21
#include "disk-io.h"
21
22
#include "hash.h"
219
220
        return btrfs_match_dir_item_name(root, path, name, name_len);
220
221
}
221
222
 
 
223
struct btrfs_dir_item *btrfs_lookup_dir_index(struct btrfs_trans_handle *trans,
 
224
                                              struct btrfs_root *root,
 
225
                                              struct btrfs_path *path, u64 dir,
 
226
                                              const char *name, int name_len,
 
227
                                              u64 index, int mod)
 
228
{
 
229
        int ret;
 
230
        struct btrfs_key key;
 
231
        int ins_len = mod < 0 ? -1 : 0;
 
232
        int cow = mod != 0;
 
233
 
 
234
        key.objectid = dir;
 
235
        key.type = BTRFS_DIR_INDEX_KEY;
 
236
        key.offset = index;
 
237
 
 
238
        ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
 
239
        if (ret < 0)
 
240
                return ERR_PTR(ret);
 
241
        if (ret > 0)
 
242
                return ERR_PTR(-ENOENT);
 
243
 
 
244
        return btrfs_match_dir_item_name(root, path, name, name_len);
 
245
}
 
246
 
 
247
/*
 
248
 * given a pointer into a directory item, delete it.  This
 
249
 * handles items that have more than one entry in them.
 
250
 */
 
251
int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
 
252
                              struct btrfs_root *root,
 
253
                              struct btrfs_path *path,
 
254
                              struct btrfs_dir_item *di)
 
255
{
 
256
 
 
257
        struct extent_buffer *leaf;
 
258
        u32 sub_item_len;
 
259
        u32 item_len;
 
260
        int ret = 0;
 
261
 
 
262
        leaf = path->nodes[0];
 
263
        sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di) +
 
264
                btrfs_dir_data_len(leaf, di);
 
265
        item_len = btrfs_item_size_nr(leaf, path->slots[0]);
 
266
        if (sub_item_len == item_len) {
 
267
                ret = btrfs_del_item(trans, root, path);
 
268
        } else {
 
269
                unsigned long ptr = (unsigned long)di;
 
270
                unsigned long start;
 
271
 
 
272
                start = btrfs_item_ptr_offset(leaf, path->slots[0]);
 
273
                memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
 
274
                        item_len - (ptr + sub_item_len - start));
 
275
                btrfs_truncate_item(trans, root, path, item_len - sub_item_len, 1);
 
276
        }
 
277
        return ret;
 
278
}
 
279
 
 
280
int verify_dir_item(struct btrfs_root *root,
 
281
                    struct extent_buffer *leaf,
 
282
                    struct btrfs_dir_item *dir_item)
 
283
{
 
284
        u16 namelen = BTRFS_NAME_LEN;
 
285
        u8 type = btrfs_dir_type(leaf, dir_item);
 
286
 
 
287
        if (type >= BTRFS_FT_MAX) {
 
288
                fprintf(stderr, "invalid dir item type: %d",
 
289
                       (int)type);
 
290
                return 1;
 
291
        }
 
292
 
 
293
        if (type == BTRFS_FT_XATTR)
 
294
                namelen = XATTR_NAME_MAX;
 
295
 
 
296
        if (btrfs_dir_name_len(leaf, dir_item) > namelen) {
 
297
                fprintf(stderr, "invalid dir item name len: %u",
 
298
                       (unsigned)btrfs_dir_data_len(leaf, dir_item));
 
299
                return 1;
 
300
        }
 
301
 
 
302
        /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */
 
303
        if ((btrfs_dir_data_len(leaf, dir_item) +
 
304
             btrfs_dir_name_len(leaf, dir_item)) > BTRFS_MAX_XATTR_SIZE(root)) {
 
305
                fprintf(stderr, "invalid dir item name + data len: %u + %u",
 
306
                       (unsigned)btrfs_dir_name_len(leaf, dir_item),
 
307
                       (unsigned)btrfs_dir_data_len(leaf, dir_item));
 
308
                return 1;
 
309
        }
 
310
 
 
311
        return 0;
 
312
}
 
313
 
222
314
static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
223
315
                              struct btrfs_path *path,
224
316
                              const char *name, int name_len)
233
325
        leaf = path->nodes[0];
234
326
        dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
235
327
        total_len = btrfs_item_size_nr(leaf, path->slots[0]);
 
328
        if (verify_dir_item(root, leaf, dir_item))
 
329
                return NULL;
 
330
 
236
331
        while(cur < total_len) {
237
332
                this_len = sizeof(*dir_item) +
238
333
                        btrfs_dir_name_len(leaf, dir_item) +
239
334
                        btrfs_dir_data_len(leaf, dir_item);
 
335
                if (this_len > (total_len - cur)) {
 
336
                        fprintf(stderr, "invalid dir item size\n");
 
337
                        return NULL;
 
338
                }
 
339
 
240
340
                name_ptr = (unsigned long)(dir_item + 1);
241
341
 
242
342
                if (btrfs_dir_name_len(leaf, dir_item) == name_len &&