OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [udf/] [namei.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * namei.c
3
 *
4
 * PURPOSE
5
 *      Inode name handling routines for the OSTA-UDF(tm) filesystem.
6
 *
7
 * COPYRIGHT
8
 *      This file is distributed under the terms of the GNU General Public
9
 *      License (GPL). Copies of the GPL can be obtained from:
10
 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
11
 *      Each contributing author retains all rights to their own work.
12
 *
13
 *  (C) 1998-2004 Ben Fennema
14
 *  (C) 1999-2000 Stelias Computing Inc
15
 *
16
 * HISTORY
17
 *
18
 *  12/12/98 blf  Created. Split out the lookup code from dir.c
19
 *  04/19/99 blf  link, mknod, symlink support
20
 */
21
 
22
#include "udfdecl.h"
23
 
24
#include "udf_i.h"
25
#include "udf_sb.h"
26
#include <linux/string.h>
27
#include <linux/errno.h>
28
#include <linux/mm.h>
29
#include <linux/slab.h>
30
#include <linux/quotaops.h>
31
#include <linux/smp_lock.h>
32
#include <linux/buffer_head.h>
33
#include <linux/sched.h>
34
 
35
static inline int udf_match(int len1, const char *name1, int len2,
36
                            const char *name2)
37
{
38
        if (len1 != len2)
39
                return 0;
40
 
41
        return !memcmp(name1, name2, len1);
42
}
43
 
44
int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
45
                 struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh,
46
                 uint8_t * impuse, uint8_t * fileident)
47
{
48
        uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(tag);
49
        uint16_t crc;
50
        uint8_t checksum = 0;
51
        int i;
52
        int offset;
53
        uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse);
54
        uint8_t lfi = cfi->lengthFileIdent;
55
        int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
56
                sizeof(struct fileIdentDesc);
57
        int adinicb = 0;
58
 
59
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
60
                adinicb = 1;
61
 
62
        offset = fibh->soffset + sizeof(struct fileIdentDesc);
63
 
64
        if (impuse) {
65
                if (adinicb || (offset + liu < 0)) {
66
                        memcpy((uint8_t *)sfi->impUse, impuse, liu);
67
                } else if (offset >= 0) {
68
                        memcpy(fibh->ebh->b_data + offset, impuse, liu);
69
                } else {
70
                        memcpy((uint8_t *)sfi->impUse, impuse, -offset);
71
                        memcpy(fibh->ebh->b_data, impuse - offset, liu + offset);
72
                }
73
        }
74
 
75
        offset += liu;
76
 
77
        if (fileident) {
78
                if (adinicb || (offset + lfi < 0)) {
79
                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
80
                } else if (offset >= 0) {
81
                        memcpy(fibh->ebh->b_data + offset, fileident, lfi);
82
                } else {
83
                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident, -offset);
84
                        memcpy(fibh->ebh->b_data, fileident - offset, lfi + offset);
85
                }
86
        }
87
 
88
        offset += lfi;
89
 
90
        if (adinicb || (offset + padlen < 0)) {
91
                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
92
        } else if (offset >= 0) {
93
                memset(fibh->ebh->b_data + offset, 0x00, padlen);
94
        } else {
95
                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, -offset);
96
                memset(fibh->ebh->b_data, 0x00, padlen + offset);
97
        }
98
 
99
        crc = udf_crc((uint8_t *)cfi + sizeof(tag),
100
                      sizeof(struct fileIdentDesc) - sizeof(tag), 0);
101
 
102
        if (fibh->sbh == fibh->ebh) {
103
                crc = udf_crc((uint8_t *)sfi->impUse,
104
                              crclen + sizeof(tag) - sizeof(struct fileIdentDesc), crc);
105
        } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
106
                crc = udf_crc(fibh->ebh->b_data + sizeof(struct fileIdentDesc) + fibh->soffset,
107
                              crclen + sizeof(tag) - sizeof(struct fileIdentDesc), crc);
108
        } else {
109
                crc = udf_crc((uint8_t *)sfi->impUse,
110
                              -fibh->soffset - sizeof(struct fileIdentDesc), crc);
111
                crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
112
        }
113
 
114
        cfi->descTag.descCRC = cpu_to_le16(crc);
115
        cfi->descTag.descCRCLength = cpu_to_le16(crclen);
116
 
117
        for (i = 0; i < 16; i++) {
118
                if (i != 4)
119
                        checksum += ((uint8_t *)&cfi->descTag)[i];
120
        }
121
 
122
        cfi->descTag.tagChecksum = checksum;
123
        if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset)) {
124
                memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
125
        } else {
126
                memcpy((uint8_t *)sfi, (uint8_t *)cfi, -fibh->soffset);
127
                memcpy(fibh->ebh->b_data, (uint8_t *)cfi - fibh->soffset,
128
                       sizeof(struct fileIdentDesc) + fibh->soffset);
129
        }
130
 
131
        if (adinicb) {
132
                mark_inode_dirty(inode);
133
        } else {
134
                if (fibh->sbh != fibh->ebh)
135
                        mark_buffer_dirty_inode(fibh->ebh, inode);
136
                mark_buffer_dirty_inode(fibh->sbh, inode);
137
        }
138
        return 0;
139
}
140
 
141
static struct fileIdentDesc *udf_find_entry(struct inode *dir,
142
                                            struct dentry *dentry,
143
                                            struct udf_fileident_bh *fibh,
144
                                            struct fileIdentDesc *cfi)
145
{
146
        struct fileIdentDesc *fi = NULL;
147
        loff_t f_pos;
148
        int block, flen;
149
        char fname[UDF_NAME_LEN];
150
        char *nameptr;
151
        uint8_t lfi;
152
        uint16_t liu;
153
        loff_t size;
154
        kernel_lb_addr eloc;
155
        uint32_t elen;
156
        sector_t offset;
157
        struct extent_position epos = {};
158
 
159
        size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
160
        f_pos = (udf_ext0_offset(dir) >> 2);
161
 
162
        fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
163
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
164
                fibh->sbh = fibh->ebh = NULL;
165
        } else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
166
                              &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
167
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
168
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
169
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
170
                                epos.offset -= sizeof(short_ad);
171
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
172
                                epos.offset -= sizeof(long_ad);
173
                } else {
174
                        offset = 0;
175
                }
176
 
177
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block))) {
178
                        brelse(epos.bh);
179
                        return NULL;
180
                }
181
        } else {
182
                brelse(epos.bh);
183
                return NULL;
184
        }
185
 
186
        while ((f_pos < size)) {
187
                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
188
                                        &elen, &offset);
189
                if (!fi) {
190
                        if (fibh->sbh != fibh->ebh)
191
                                brelse(fibh->ebh);
192
                        brelse(fibh->sbh);
193
                        brelse(epos.bh);
194
                        return NULL;
195
                }
196
 
197
                liu = le16_to_cpu(cfi->lengthOfImpUse);
198
                lfi = cfi->lengthFileIdent;
199
 
200
                if (fibh->sbh == fibh->ebh) {
201
                        nameptr = fi->fileIdent + liu;
202
                } else {
203
                        int poffset;    /* Unpaded ending offset */
204
 
205
                        poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
206
 
207
                        if (poffset >= lfi) {
208
                                nameptr = (uint8_t *)(fibh->ebh->b_data + poffset - lfi);
209
                        } else {
210
                                nameptr = fname;
211
                                memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
212
                                memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
213
                        }
214
                }
215
 
216
                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
217
                        if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE))
218
                                continue;
219
                }
220
 
221
                if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) {
222
                        if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE))
223
                                continue;
224
                }
225
 
226
                if (!lfi)
227
                        continue;
228
 
229
                if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi))) {
230
                        if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name)) {
231
                                brelse(epos.bh);
232
                                return fi;
233
                        }
234
                }
235
        }
236
 
237
        if (fibh->sbh != fibh->ebh)
238
                brelse(fibh->ebh);
239
        brelse(fibh->sbh);
240
        brelse(epos.bh);
241
 
242
        return NULL;
243
}
244
 
245
/*
246
 * udf_lookup
247
 *
248
 * PURPOSE
249
 *      Look-up the inode for a given name.
250
 *
251
 * DESCRIPTION
252
 *      Required - lookup_dentry() will return -ENOTDIR if this routine is not
253
 *      available for a directory. The filesystem is useless if this routine is
254
 *      not available for at least the filesystem's root directory.
255
 *
256
 *      This routine is passed an incomplete dentry - it must be completed by
257
 *      calling d_add(dentry, inode). If the name does not exist, then the
258
 *      specified inode must be set to null. An error should only be returned
259
 *      when the lookup fails for a reason other than the name not existing.
260
 *      Note that the directory inode semaphore is held during the call.
261
 *
262
 *      Refer to lookup_dentry() in fs/namei.c
263
 *      lookup_dentry() -> lookup() -> real_lookup() -> .
264
 *
265
 * PRE-CONDITIONS
266
 *      dir                     Pointer to inode of parent directory.
267
 *      dentry                  Pointer to dentry to complete.
268
 *      nd                      Pointer to lookup nameidata
269
 *
270
 * POST-CONDITIONS
271
 *      <return>                Zero on success.
272
 *
273
 * HISTORY
274
 *      July 1, 1997 - Andrew E. Mileski
275
 *      Written, tested, and released.
276
 */
277
 
278
static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
279
                                 struct nameidata *nd)
280
{
281
        struct inode *inode = NULL;
282
        struct fileIdentDesc cfi;
283
        struct udf_fileident_bh fibh;
284
 
285
        if (dentry->d_name.len > UDF_NAME_LEN - 2)
286
                return ERR_PTR(-ENAMETOOLONG);
287
 
288
        lock_kernel();
289
#ifdef UDF_RECOVERY
290
        /* temporary shorthand for specifying files by inode number */
291
        if (!strncmp(dentry->d_name.name, ".B=", 3)) {
292
                kernel_lb_addr lb = {
293
                        .logicalBlockNum = 0,
294
                        .partitionReferenceNum = simple_strtoul(dentry->d_name.name + 3,
295
                                                                NULL, 0),
296
                };
297
                inode = udf_iget(dir->i_sb, lb);
298
                if (!inode) {
299
                        unlock_kernel();
300
                        return ERR_PTR(-EACCES);
301
                }
302
        }
303
        else
304
#endif /* UDF_RECOVERY */
305
 
306
        if (udf_find_entry(dir, dentry, &fibh, &cfi)) {
307
                if (fibh.sbh != fibh.ebh)
308
                        brelse(fibh.ebh);
309
                brelse(fibh.sbh);
310
 
311
                inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
312
                if (!inode) {
313
                        unlock_kernel();
314
                        return ERR_PTR(-EACCES);
315
                }
316
        }
317
        unlock_kernel();
318
        d_add(dentry, inode);
319
 
320
        return NULL;
321
}
322
 
323
static struct fileIdentDesc *udf_add_entry(struct inode *dir,
324
                                           struct dentry *dentry,
325
                                           struct udf_fileident_bh *fibh,
326
                                           struct fileIdentDesc *cfi, int *err)
327
{
328
        struct super_block *sb;
329
        struct fileIdentDesc *fi = NULL;
330
        char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
331
        int namelen;
332
        loff_t f_pos;
333
        int flen;
334
        char *nameptr;
335
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
336
        int nfidlen;
337
        uint8_t lfi;
338
        uint16_t liu;
339
        int block;
340
        kernel_lb_addr eloc;
341
        uint32_t elen;
342
        sector_t offset;
343
        struct extent_position epos = {};
344
 
345
        sb = dir->i_sb;
346
 
347
        if (dentry) {
348
                if (!dentry->d_name.len) {
349
                        *err = -EINVAL;
350
                        return NULL;
351
                }
352
                if (!(namelen = udf_put_filename(sb, dentry->d_name.name, name,
353
                                                 dentry->d_name.len))) {
354
                        *err = -ENAMETOOLONG;
355
                        return NULL;
356
                }
357
        } else {
358
                namelen = 0;
359
        }
360
 
361
        nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3;
362
 
363
        f_pos = (udf_ext0_offset(dir) >> 2);
364
 
365
        fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
366
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
367
                fibh->sbh = fibh->ebh = NULL;
368
        } else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
369
                              &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
370
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
371
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
372
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
373
                                epos.offset -= sizeof(short_ad);
374
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
375
                                epos.offset -= sizeof(long_ad);
376
                } else {
377
                        offset = 0;
378
                }
379
 
380
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block))) {
381
                        brelse(epos.bh);
382
                        *err = -EIO;
383
                        return NULL;
384
                }
385
 
386
                block = UDF_I_LOCATION(dir).logicalBlockNum;
387
 
388
        } else {
389
                block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
390
                fibh->sbh = fibh->ebh = NULL;
391
                fibh->soffset = fibh->eoffset = sb->s_blocksize;
392
                goto add;
393
        }
394
 
395
        while ((f_pos < size)) {
396
                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
397
                                        &elen, &offset);
398
 
399
                if (!fi) {
400
                        if (fibh->sbh != fibh->ebh)
401
                                brelse(fibh->ebh);
402
                        brelse(fibh->sbh);
403
                        brelse(epos.bh);
404
                        *err = -EIO;
405
                        return NULL;
406
                }
407
 
408
                liu = le16_to_cpu(cfi->lengthOfImpUse);
409
                lfi = cfi->lengthFileIdent;
410
 
411
                if (fibh->sbh == fibh->ebh) {
412
                        nameptr = fi->fileIdent + liu;
413
                } else {
414
                        int poffset;    /* Unpaded ending offset */
415
 
416
                        poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
417
 
418
                        if (poffset >= lfi) {
419
                                nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
420
                        } else {
421
                                nameptr = fname;
422
                                memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
423
                                memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
424
                        }
425
                }
426
 
427
                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
428
                        if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen) {
429
                                brelse(epos.bh);
430
                                cfi->descTag.tagSerialNum = cpu_to_le16(1);
431
                                cfi->fileVersionNum = cpu_to_le16(1);
432
                                cfi->fileCharacteristics = 0;
433
                                cfi->lengthFileIdent = namelen;
434
                                cfi->lengthOfImpUse = cpu_to_le16(0);
435
                                if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
436
                                        return fi;
437
                                } else {
438
                                        *err = -EIO;
439
                                        return NULL;
440
                                }
441
                        }
442
                }
443
 
444
                if (!lfi || !dentry)
445
                        continue;
446
 
447
                if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
448
                    udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name)) {
449
                        if (fibh->sbh != fibh->ebh)
450
                                brelse(fibh->ebh);
451
                        brelse(fibh->sbh);
452
                        brelse(epos.bh);
453
                        *err = -EEXIST;
454
                        return NULL;
455
                }
456
        }
457
 
458
add:
459
        f_pos += nfidlen;
460
 
461
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
462
            sb->s_blocksize - fibh->eoffset < nfidlen) {
463
                brelse(epos.bh);
464
                epos.bh = NULL;
465
                fibh->soffset -= udf_ext0_offset(dir);
466
                fibh->eoffset -= udf_ext0_offset(dir);
467
                f_pos -= (udf_ext0_offset(dir) >> 2);
468
                if (fibh->sbh != fibh->ebh)
469
                        brelse(fibh->ebh);
470
                brelse(fibh->sbh);
471
                if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
472
                        return NULL;
473
                epos.block = UDF_I_LOCATION(dir);
474
                eloc.logicalBlockNum = block;
475
                eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
476
                elen = dir->i_sb->s_blocksize;
477
                epos.offset = udf_file_entry_alloc_offset(dir);
478
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
479
                        epos.offset += sizeof(short_ad);
480
                else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
481
                        epos.offset += sizeof(long_ad);
482
        }
483
 
484
        if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
485
                fibh->soffset = fibh->eoffset;
486
                fibh->eoffset += nfidlen;
487
                if (fibh->sbh != fibh->ebh) {
488
                        brelse(fibh->sbh);
489
                        fibh->sbh = fibh->ebh;
490
                }
491
 
492
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
493
                        block = UDF_I_LOCATION(dir).logicalBlockNum;
494
                        fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset -
495
                                                      udf_ext0_offset(dir) +
496
                                                      UDF_I_LENEATTR(dir));
497
                } else {
498
                        block = eloc.logicalBlockNum + ((elen - 1) >>
499
                                                        dir->i_sb->s_blocksize_bits);
500
                        fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
501
                }
502
        } else {
503
                fibh->soffset = fibh->eoffset - sb->s_blocksize;
504
                fibh->eoffset += nfidlen - sb->s_blocksize;
505
                if (fibh->sbh != fibh->ebh) {
506
                        brelse(fibh->sbh);
507
                        fibh->sbh = fibh->ebh;
508
                }
509
 
510
                block = eloc.logicalBlockNum + ((elen - 1) >>
511
                                                dir->i_sb->s_blocksize_bits);
512
                fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err);
513
                if (!fibh->ebh) {
514
                        brelse(epos.bh);
515
                        brelse(fibh->sbh);
516
                        return NULL;
517
                }
518
 
519
                if (!fibh->soffset) {
520
                        if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
521
                            (EXT_RECORDED_ALLOCATED >> 30)) {
522
                                block = eloc.logicalBlockNum + ((elen - 1) >>
523
                                        dir->i_sb->s_blocksize_bits);
524
                        } else {
525
                                block++;
526
                        }
527
 
528
                        brelse(fibh->sbh);
529
                        fibh->sbh = fibh->ebh;
530
                        fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
531
                } else {
532
                        fi = (struct fileIdentDesc *)
533
                                (fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
534
                }
535
        }
536
 
537
        memset(cfi, 0, sizeof(struct fileIdentDesc));
538
        if (UDF_SB_UDFREV(sb) >= 0x0200)
539
                udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, sizeof(tag));
540
        else
541
                udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, sizeof(tag));
542
        cfi->fileVersionNum = cpu_to_le16(1);
543
        cfi->lengthFileIdent = namelen;
544
        cfi->lengthOfImpUse = cpu_to_le16(0);
545
        if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
546
                brelse(epos.bh);
547
                dir->i_size += nfidlen;
548
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
549
                        UDF_I_LENALLOC(dir) += nfidlen;
550
                mark_inode_dirty(dir);
551
                return fi;
552
        } else {
553
                brelse(epos.bh);
554
                if (fibh->sbh != fibh->ebh)
555
                        brelse(fibh->ebh);
556
                brelse(fibh->sbh);
557
                *err = -EIO;
558
                return NULL;
559
        }
560
}
561
 
562
static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
563
                            struct udf_fileident_bh *fibh,
564
                            struct fileIdentDesc *cfi)
565
{
566
        cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED;
567
 
568
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
569
                memset(&(cfi->icb), 0x00, sizeof(long_ad));
570
 
571
        return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
572
}
573
 
574
static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
575
                      struct nameidata *nd)
576
{
577
        struct udf_fileident_bh fibh;
578
        struct inode *inode;
579
        struct fileIdentDesc cfi, *fi;
580
        int err;
581
 
582
        lock_kernel();
583
        inode = udf_new_inode(dir, mode, &err);
584
        if (!inode) {
585
                unlock_kernel();
586
                return err;
587
        }
588
 
589
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
590
                inode->i_data.a_ops = &udf_adinicb_aops;
591
        else
592
                inode->i_data.a_ops = &udf_aops;
593
        inode->i_op = &udf_file_inode_operations;
594
        inode->i_fop = &udf_file_operations;
595
        inode->i_mode = mode;
596
        mark_inode_dirty(inode);
597
 
598
        if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
599
                inode->i_nlink--;
600
                mark_inode_dirty(inode);
601
                iput(inode);
602
                unlock_kernel();
603
                return err;
604
        }
605
        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
606
        cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
607
        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
608
                cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
609
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
610
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
611
                mark_inode_dirty(dir);
612
        }
613
        if (fibh.sbh != fibh.ebh)
614
                brelse(fibh.ebh);
615
        brelse(fibh.sbh);
616
        unlock_kernel();
617
        d_instantiate(dentry, inode);
618
 
619
        return 0;
620
}
621
 
622
static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
623
                     dev_t rdev)
624
{
625
        struct inode *inode;
626
        struct udf_fileident_bh fibh;
627
        struct fileIdentDesc cfi, *fi;
628
        int err;
629
 
630
        if (!old_valid_dev(rdev))
631
                return -EINVAL;
632
 
633
        lock_kernel();
634
        err = -EIO;
635
        inode = udf_new_inode(dir, mode, &err);
636
        if (!inode)
637
                goto out;
638
 
639
        inode->i_uid = current->fsuid;
640
        init_special_inode(inode, mode, rdev);
641
        if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
642
                inode->i_nlink--;
643
                mark_inode_dirty(inode);
644
                iput(inode);
645
                unlock_kernel();
646
                return err;
647
        }
648
        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
649
        cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
650
        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
651
                cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
652
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
653
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
654
                mark_inode_dirty(dir);
655
        }
656
        mark_inode_dirty(inode);
657
 
658
        if (fibh.sbh != fibh.ebh)
659
                brelse(fibh.ebh);
660
        brelse(fibh.sbh);
661
        d_instantiate(dentry, inode);
662
        err = 0;
663
 
664
out:
665
        unlock_kernel();
666
        return err;
667
}
668
 
669
static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
670
{
671
        struct inode *inode;
672
        struct udf_fileident_bh fibh;
673
        struct fileIdentDesc cfi, *fi;
674
        int err;
675
 
676
        lock_kernel();
677
        err = -EMLINK;
678
        if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1)
679
                goto out;
680
 
681
        err = -EIO;
682
        inode = udf_new_inode(dir, S_IFDIR, &err);
683
        if (!inode)
684
                goto out;
685
 
686
        inode->i_op = &udf_dir_inode_operations;
687
        inode->i_fop = &udf_dir_operations;
688
        if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err))) {
689
                inode->i_nlink--;
690
                mark_inode_dirty(inode);
691
                iput(inode);
692
                goto out;
693
        }
694
        inode->i_nlink = 2;
695
        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
696
        cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));
697
        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
698
                cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
699
        cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
700
        udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
701
        brelse(fibh.sbh);
702
        inode->i_mode = S_IFDIR | mode;
703
        if (dir->i_mode & S_ISGID)
704
                inode->i_mode |= S_ISGID;
705
        mark_inode_dirty(inode);
706
 
707
        if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
708
                inode->i_nlink = 0;
709
                mark_inode_dirty(inode);
710
                iput(inode);
711
                goto out;
712
        }
713
        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
714
        cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
715
        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
716
                cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
717
        cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
718
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
719
        inc_nlink(dir);
720
        mark_inode_dirty(dir);
721
        d_instantiate(dentry, inode);
722
        if (fibh.sbh != fibh.ebh)
723
                brelse(fibh.ebh);
724
        brelse(fibh.sbh);
725
        err = 0;
726
 
727
out:
728
        unlock_kernel();
729
        return err;
730
}
731
 
732
static int empty_dir(struct inode *dir)
733
{
734
        struct fileIdentDesc *fi, cfi;
735
        struct udf_fileident_bh fibh;
736
        loff_t f_pos;
737
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
738
        int block;
739
        kernel_lb_addr eloc;
740
        uint32_t elen;
741
        sector_t offset;
742
        struct extent_position epos = {};
743
 
744
        f_pos = (udf_ext0_offset(dir) >> 2);
745
 
746
        fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
747
 
748
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
749
                fibh.sbh = fibh.ebh = NULL;
750
        } else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
751
                              &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
752
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
753
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
754
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
755
                                epos.offset -= sizeof(short_ad);
756
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
757
                                epos.offset -= sizeof(long_ad);
758
                } else {
759
                        offset = 0;
760
                }
761
 
762
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
763
                        brelse(epos.bh);
764
                        return 0;
765
                }
766
        } else {
767
                brelse(epos.bh);
768
                return 0;
769
        }
770
 
771
        while ((f_pos < size)) {
772
                fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc,
773
                                        &elen, &offset);
774
                if (!fi) {
775
                        if (fibh.sbh != fibh.ebh)
776
                                brelse(fibh.ebh);
777
                        brelse(fibh.sbh);
778
                        brelse(epos.bh);
779
                        return 0;
780
                }
781
 
782
                if (cfi.lengthFileIdent &&
783
                    (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) {
784
                        if (fibh.sbh != fibh.ebh)
785
                                brelse(fibh.ebh);
786
                        brelse(fibh.sbh);
787
                        brelse(epos.bh);
788
                        return 0;
789
                }
790
        }
791
 
792
        if (fibh.sbh != fibh.ebh)
793
                brelse(fibh.ebh);
794
        brelse(fibh.sbh);
795
        brelse(epos.bh);
796
 
797
        return 1;
798
}
799
 
800
static int udf_rmdir(struct inode *dir, struct dentry *dentry)
801
{
802
        int retval;
803
        struct inode *inode = dentry->d_inode;
804
        struct udf_fileident_bh fibh;
805
        struct fileIdentDesc *fi, cfi;
806
        kernel_lb_addr tloc;
807
 
808
        retval = -ENOENT;
809
        lock_kernel();
810
        fi = udf_find_entry(dir, dentry, &fibh, &cfi);
811
        if (!fi)
812
                goto out;
813
 
814
        retval = -EIO;
815
        tloc = lelb_to_cpu(cfi.icb.extLocation);
816
        if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino)
817
                goto end_rmdir;
818
        retval = -ENOTEMPTY;
819
        if (!empty_dir(inode))
820
                goto end_rmdir;
821
        retval = udf_delete_entry(dir, fi, &fibh, &cfi);
822
        if (retval)
823
                goto end_rmdir;
824
        if (inode->i_nlink != 2)
825
                udf_warning(inode->i_sb, "udf_rmdir",
826
                            "empty directory has nlink != 2 (%d)",
827
                            inode->i_nlink);
828
        clear_nlink(inode);
829
        inode->i_size = 0;
830
        inode_dec_link_count(dir);
831
        inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
832
        mark_inode_dirty(dir);
833
 
834
end_rmdir:
835
        if (fibh.sbh != fibh.ebh)
836
                brelse(fibh.ebh);
837
        brelse(fibh.sbh);
838
 
839
out:
840
        unlock_kernel();
841
        return retval;
842
}
843
 
844
static int udf_unlink(struct inode *dir, struct dentry *dentry)
845
{
846
        int retval;
847
        struct inode *inode = dentry->d_inode;
848
        struct udf_fileident_bh fibh;
849
        struct fileIdentDesc *fi;
850
        struct fileIdentDesc cfi;
851
        kernel_lb_addr tloc;
852
 
853
        retval = -ENOENT;
854
        lock_kernel();
855
        fi = udf_find_entry(dir, dentry, &fibh, &cfi);
856
        if (!fi)
857
                goto out;
858
 
859
        retval = -EIO;
860
        tloc = lelb_to_cpu(cfi.icb.extLocation);
861
        if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino)
862
                goto end_unlink;
863
 
864
        if (!inode->i_nlink) {
865
                udf_debug("Deleting nonexistent file (%lu), %d\n",
866
                          inode->i_ino, inode->i_nlink);
867
                inode->i_nlink = 1;
868
        }
869
        retval = udf_delete_entry(dir, fi, &fibh, &cfi);
870
        if (retval)
871
                goto end_unlink;
872
        dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
873
        mark_inode_dirty(dir);
874
        inode_dec_link_count(inode);
875
        inode->i_ctime = dir->i_ctime;
876
        retval = 0;
877
 
878
end_unlink:
879
        if (fibh.sbh != fibh.ebh)
880
                brelse(fibh.ebh);
881
        brelse(fibh.sbh);
882
 
883
out:
884
        unlock_kernel();
885
        return retval;
886
}
887
 
888
static int udf_symlink(struct inode *dir, struct dentry *dentry,
889
                       const char *symname)
890
{
891
        struct inode *inode;
892
        struct pathComponent *pc;
893
        char *compstart;
894
        struct udf_fileident_bh fibh;
895
        struct extent_position epos = {};
896
        int eoffset, elen = 0;
897
        struct fileIdentDesc *fi;
898
        struct fileIdentDesc cfi;
899
        char *ea;
900
        int err;
901
        int block;
902
        char name[UDF_NAME_LEN];
903
        int namelen;
904
 
905
        lock_kernel();
906
        if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
907
                goto out;
908
 
909
        inode->i_mode = S_IFLNK | S_IRWXUGO;
910
        inode->i_data.a_ops = &udf_symlink_aops;
911
        inode->i_op = &page_symlink_inode_operations;
912
 
913
        if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB) {
914
                kernel_lb_addr eloc;
915
                uint32_t elen;
916
 
917
                block = udf_new_block(inode->i_sb, inode,
918
                                      UDF_I_LOCATION(inode).partitionReferenceNum,
919
                                      UDF_I_LOCATION(inode).logicalBlockNum, &err);
920
                if (!block)
921
                        goto out_no_entry;
922
                epos.block = UDF_I_LOCATION(inode);
923
                epos.offset = udf_file_entry_alloc_offset(inode);
924
                epos.bh = NULL;
925
                eloc.logicalBlockNum = block;
926
                eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
927
                elen = inode->i_sb->s_blocksize;
928
                UDF_I_LENEXTENTS(inode) = elen;
929
                udf_add_aext(inode, &epos, eloc, elen, 0);
930
                brelse(epos.bh);
931
 
932
                block = udf_get_pblock(inode->i_sb, block,
933
                                       UDF_I_LOCATION(inode).partitionReferenceNum, 0);
934
                epos.bh = udf_tread(inode->i_sb, block);
935
                lock_buffer(epos.bh);
936
                memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
937
                set_buffer_uptodate(epos.bh);
938
                unlock_buffer(epos.bh);
939
                mark_buffer_dirty_inode(epos.bh, inode);
940
                ea = epos.bh->b_data + udf_ext0_offset(inode);
941
        } else {
942
                ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
943
        }
944
 
945
        eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
946
        pc = (struct pathComponent *)ea;
947
 
948
        if (*symname == '/') {
949
                do {
950
                        symname++;
951
                } while (*symname == '/');
952
 
953
                pc->componentType = 1;
954
                pc->lengthComponentIdent = 0;
955
                pc->componentFileVersionNum = 0;
956
                pc += sizeof(struct pathComponent);
957
                elen += sizeof(struct pathComponent);
958
        }
959
 
960
        err = -ENAMETOOLONG;
961
 
962
        while (*symname) {
963
                if (elen + sizeof(struct pathComponent) > eoffset)
964
                        goto out_no_entry;
965
 
966
                pc = (struct pathComponent *)(ea + elen);
967
 
968
                compstart = (char *)symname;
969
 
970
                do {
971
                        symname++;
972
                } while (*symname && *symname != '/');
973
 
974
                pc->componentType = 5;
975
                pc->lengthComponentIdent = 0;
976
                pc->componentFileVersionNum = 0;
977
                if (compstart[0] == '.') {
978
                        if ((symname - compstart) == 1)
979
                                pc->componentType = 4;
980
                        else if ((symname - compstart) == 2 && compstart[1] == '.')
981
                                pc->componentType = 3;
982
                }
983
 
984
                if (pc->componentType == 5) {
985
                        namelen = udf_put_filename(inode->i_sb, compstart, name,
986
                                                   symname - compstart);
987
                        if (!namelen)
988
                                goto out_no_entry;
989
 
990
                        if (elen + sizeof(struct pathComponent) + namelen > eoffset)
991
                                goto out_no_entry;
992
                        else
993
                                pc->lengthComponentIdent = namelen;
994
 
995
                        memcpy(pc->componentIdent, name, namelen);
996
                }
997
 
998
                elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
999
 
1000
                if (*symname) {
1001
                        do {
1002
                                symname++;
1003
                        } while (*symname == '/');
1004
                }
1005
        }
1006
 
1007
        brelse(epos.bh);
1008
        inode->i_size = elen;
1009
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
1010
                UDF_I_LENALLOC(inode) = inode->i_size;
1011
        mark_inode_dirty(inode);
1012
 
1013
        if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
1014
                goto out_no_entry;
1015
        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
1016
        cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
1017
        if (UDF_SB_LVIDBH(inode->i_sb)) {
1018
                struct logicalVolHeaderDesc *lvhd;
1019
                uint64_t uniqueID;
1020
                lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
1021
                uniqueID = le64_to_cpu(lvhd->uniqueID);
1022
                *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
1023
                        cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
1024
                if (!(++uniqueID & 0x00000000FFFFFFFFUL))
1025
                        uniqueID += 16;
1026
                lvhd->uniqueID = cpu_to_le64(uniqueID);
1027
                mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb));
1028
        }
1029
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
1030
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1031
                mark_inode_dirty(dir);
1032
        }
1033
        if (fibh.sbh != fibh.ebh)
1034
                brelse(fibh.ebh);
1035
        brelse(fibh.sbh);
1036
        d_instantiate(dentry, inode);
1037
        err = 0;
1038
 
1039
out:
1040
        unlock_kernel();
1041
        return err;
1042
 
1043
out_no_entry:
1044
        inode_dec_link_count(inode);
1045
        iput(inode);
1046
        goto out;
1047
}
1048
 
1049
static int udf_link(struct dentry *old_dentry, struct inode *dir,
1050
                    struct dentry *dentry)
1051
{
1052
        struct inode *inode = old_dentry->d_inode;
1053
        struct udf_fileident_bh fibh;
1054
        struct fileIdentDesc cfi, *fi;
1055
        int err;
1056
 
1057
        lock_kernel();
1058
        if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) {
1059
                unlock_kernel();
1060
                return -EMLINK;
1061
        }
1062
 
1063
        if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
1064
                unlock_kernel();
1065
                return err;
1066
        }
1067
        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
1068
        cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
1069
        if (UDF_SB_LVIDBH(inode->i_sb)) {
1070
                struct logicalVolHeaderDesc *lvhd;
1071
                uint64_t uniqueID;
1072
                lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
1073
                uniqueID = le64_to_cpu(lvhd->uniqueID);
1074
                *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
1075
                        cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
1076
                if (!(++uniqueID & 0x00000000FFFFFFFFUL))
1077
                        uniqueID += 16;
1078
                lvhd->uniqueID = cpu_to_le64(uniqueID);
1079
                mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb));
1080
        }
1081
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
1082
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) {
1083
                mark_inode_dirty(dir);
1084
        }
1085
 
1086
        if (fibh.sbh != fibh.ebh)
1087
                brelse(fibh.ebh);
1088
        brelse(fibh.sbh);
1089
        inc_nlink(inode);
1090
        inode->i_ctime = current_fs_time(inode->i_sb);
1091
        mark_inode_dirty(inode);
1092
        atomic_inc(&inode->i_count);
1093
        d_instantiate(dentry, inode);
1094
        unlock_kernel();
1095
 
1096
        return 0;
1097
}
1098
 
1099
/* Anybody can rename anything with this: the permission checks are left to the
1100
 * higher-level routines.
1101
 */
1102
static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
1103
                      struct inode *new_dir, struct dentry *new_dentry)
1104
{
1105
        struct inode *old_inode = old_dentry->d_inode;
1106
        struct inode *new_inode = new_dentry->d_inode;
1107
        struct udf_fileident_bh ofibh, nfibh;
1108
        struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;
1109
        struct buffer_head *dir_bh = NULL;
1110
        int retval = -ENOENT;
1111
        kernel_lb_addr tloc;
1112
 
1113
        lock_kernel();
1114
        if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi))) {
1115
                if (ofibh.sbh != ofibh.ebh)
1116
                        brelse(ofibh.ebh);
1117
                brelse(ofibh.sbh);
1118
        }
1119
        tloc = lelb_to_cpu(ocfi.icb.extLocation);
1120
        if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0)
1121
            != old_inode->i_ino)
1122
                goto end_rename;
1123
 
1124
        nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi);
1125
        if (nfi) {
1126
                if (!new_inode) {
1127
                        if (nfibh.sbh != nfibh.ebh)
1128
                                brelse(nfibh.ebh);
1129
                        brelse(nfibh.sbh);
1130
                        nfi = NULL;
1131
                }
1132
        }
1133
        if (S_ISDIR(old_inode->i_mode)) {
1134
                uint32_t offset = udf_ext0_offset(old_inode);
1135
 
1136
                if (new_inode) {
1137
                        retval = -ENOTEMPTY;
1138
                        if (!empty_dir(new_inode))
1139
                                goto end_rename;
1140
                }
1141
                retval = -EIO;
1142
                if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) {
1143
                        dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
1144
                                                   (UDF_I_EFE(old_inode) ?
1145
                                                    sizeof(struct extendedFileEntry) :
1146
                                                    sizeof(struct fileEntry)),
1147
                                                   old_inode->i_sb->s_blocksize, &offset);
1148
                } else {
1149
                        dir_bh = udf_bread(old_inode, 0, 0, &retval);
1150
                        if (!dir_bh)
1151
                                goto end_rename;
1152
                        dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
1153
                }
1154
                if (!dir_fi)
1155
                        goto end_rename;
1156
                tloc = lelb_to_cpu(dir_fi->icb.extLocation);
1157
                if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0) != old_dir->i_ino)
1158
                        goto end_rename;
1159
 
1160
                retval = -EMLINK;
1161
                if (!new_inode && new_dir->i_nlink >= (256 << sizeof(new_dir->i_nlink)) - 1)
1162
                        goto end_rename;
1163
        }
1164
        if (!nfi) {
1165
                nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval);
1166
                if (!nfi)
1167
                        goto end_rename;
1168
        }
1169
 
1170
        /*
1171
         * Like most other Unix systems, set the ctime for inodes on a
1172
         * rename.
1173
         */
1174
        old_inode->i_ctime = current_fs_time(old_inode->i_sb);
1175
        mark_inode_dirty(old_inode);
1176
 
1177
        /*
1178
         * ok, that's it
1179
         */
1180
        ncfi.fileVersionNum = ocfi.fileVersionNum;
1181
        ncfi.fileCharacteristics = ocfi.fileCharacteristics;
1182
        memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad));
1183
        udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);
1184
 
1185
        /* The old fid may have moved - find it again */
1186
        ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi);
1187
        udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
1188
 
1189
        if (new_inode) {
1190
                new_inode->i_ctime = current_fs_time(new_inode->i_sb);
1191
                inode_dec_link_count(new_inode);
1192
        }
1193
        old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
1194
        mark_inode_dirty(old_dir);
1195
 
1196
        if (dir_fi) {
1197
                dir_fi->icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(new_dir));
1198
                udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
1199
                                                le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
1200
                if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) {
1201
                        mark_inode_dirty(old_inode);
1202
                } else {
1203
                        mark_buffer_dirty_inode(dir_bh, old_inode);
1204
                }
1205
                inode_dec_link_count(old_dir);
1206
                if (new_inode) {
1207
                        inode_dec_link_count(new_inode);
1208
                } else {
1209
                        inc_nlink(new_dir);
1210
                        mark_inode_dirty(new_dir);
1211
                }
1212
        }
1213
 
1214
        if (ofi) {
1215
                if (ofibh.sbh != ofibh.ebh)
1216
                        brelse(ofibh.ebh);
1217
                brelse(ofibh.sbh);
1218
        }
1219
 
1220
        retval = 0;
1221
 
1222
end_rename:
1223
        brelse(dir_bh);
1224
        if (nfi) {
1225
                if (nfibh.sbh != nfibh.ebh)
1226
                        brelse(nfibh.ebh);
1227
                brelse(nfibh.sbh);
1228
        }
1229
        unlock_kernel();
1230
 
1231
        return retval;
1232
}
1233
 
1234
const struct inode_operations udf_dir_inode_operations = {
1235
        .lookup                         = udf_lookup,
1236
        .create                         = udf_create,
1237
        .link                           = udf_link,
1238
        .unlink                         = udf_unlink,
1239
        .symlink                        = udf_symlink,
1240
        .mkdir                          = udf_mkdir,
1241
        .rmdir                          = udf_rmdir,
1242
        .mknod                          = udf_mknod,
1243
        .rename                         = udf_rename,
1244
};

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.