linux/fs/udf/namei.c
<<
>>
Prefs
   1/*
   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/buffer_head.h>
  31#include <linux/sched.h>
  32#include <linux/crc-itu-t.h>
  33#include <linux/exportfs.h>
  34
  35static inline int udf_match(int len1, const unsigned char *name1, int len2,
  36                            const unsigned char *name2)
  37{
  38        if (len1 != len2)
  39                return 0;
  40
  41        return !memcmp(name1, name2, len1);
  42}
  43
  44int 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(struct tag);
  49        uint16_t crc;
  50        int offset;
  51        uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse);
  52        uint8_t lfi = cfi->lengthFileIdent;
  53        int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
  54                sizeof(struct fileIdentDesc);
  55        int adinicb = 0;
  56
  57        if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
  58                adinicb = 1;
  59
  60        offset = fibh->soffset + sizeof(struct fileIdentDesc);
  61
  62        if (impuse) {
  63                if (adinicb || (offset + liu < 0)) {
  64                        memcpy((uint8_t *)sfi->impUse, impuse, liu);
  65                } else if (offset >= 0) {
  66                        memcpy(fibh->ebh->b_data + offset, impuse, liu);
  67                } else {
  68                        memcpy((uint8_t *)sfi->impUse, impuse, -offset);
  69                        memcpy(fibh->ebh->b_data, impuse - offset,
  70                                liu + offset);
  71                }
  72        }
  73
  74        offset += liu;
  75
  76        if (fileident) {
  77                if (adinicb || (offset + lfi < 0)) {
  78                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
  79                } else if (offset >= 0) {
  80                        memcpy(fibh->ebh->b_data + offset, fileident, lfi);
  81                } else {
  82                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident,
  83                                -offset);
  84                        memcpy(fibh->ebh->b_data, fileident - offset,
  85                                lfi + offset);
  86                }
  87        }
  88
  89        offset += lfi;
  90
  91        if (adinicb || (offset + padlen < 0)) {
  92                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
  93        } else if (offset >= 0) {
  94                memset(fibh->ebh->b_data + offset, 0x00, padlen);
  95        } else {
  96                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, -offset);
  97                memset(fibh->ebh->b_data, 0x00, padlen + offset);
  98        }
  99
 100        crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(struct tag),
 101                      sizeof(struct fileIdentDesc) - sizeof(struct tag));
 102
 103        if (fibh->sbh == fibh->ebh) {
 104                crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
 105                              crclen + sizeof(struct tag) -
 106                              sizeof(struct fileIdentDesc));
 107        } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
 108                crc = crc_itu_t(crc, fibh->ebh->b_data +
 109                                        sizeof(struct fileIdentDesc) +
 110                                        fibh->soffset,
 111                              crclen + sizeof(struct tag) -
 112                                        sizeof(struct fileIdentDesc));
 113        } else {
 114                crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
 115                              -fibh->soffset - sizeof(struct fileIdentDesc));
 116                crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
 117        }
 118
 119        cfi->descTag.descCRC = cpu_to_le16(crc);
 120        cfi->descTag.descCRCLength = cpu_to_le16(crclen);
 121        cfi->descTag.tagChecksum = udf_tag_checksum(&cfi->descTag);
 122
 123        if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset)) {
 124                memcpy((uint8_t *)sfi, (uint8_t *)cfi,
 125                        sizeof(struct fileIdentDesc));
 126        } else {
 127                memcpy((uint8_t *)sfi, (uint8_t *)cfi, -fibh->soffset);
 128                memcpy(fibh->ebh->b_data, (uint8_t *)cfi - fibh->soffset,
 129                       sizeof(struct fileIdentDesc) + fibh->soffset);
 130        }
 131
 132        if (adinicb) {
 133                mark_inode_dirty(inode);
 134        } else {
 135                if (fibh->sbh != fibh->ebh)
 136                        mark_buffer_dirty_inode(fibh->ebh, inode);
 137                mark_buffer_dirty_inode(fibh->sbh, inode);
 138        }
 139        return 0;
 140}
 141
 142static struct fileIdentDesc *udf_find_entry(struct inode *dir,
 143                                            const struct qstr *child,
 144                                            struct udf_fileident_bh *fibh,
 145                                            struct fileIdentDesc *cfi)
 146{
 147        struct fileIdentDesc *fi = NULL;
 148        loff_t f_pos;
 149        int block, flen;
 150        unsigned char *fname = NULL;
 151        unsigned char *nameptr;
 152        uint8_t lfi;
 153        uint16_t liu;
 154        loff_t size;
 155        struct kernel_lb_addr eloc;
 156        uint32_t elen;
 157        sector_t offset;
 158        struct extent_position epos = {};
 159        struct udf_inode_info *dinfo = UDF_I(dir);
 160        int isdotdot = child->len == 2 &&
 161                child->name[0] == '.' && child->name[1] == '.';
 162
 163        size = udf_ext0_offset(dir) + dir->i_size;
 164        f_pos = udf_ext0_offset(dir);
 165
 166        fibh->sbh = fibh->ebh = NULL;
 167        fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
 168        if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
 169                if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
 170                    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
 171                        goto out_err;
 172                block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
 173                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
 174                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 175                                epos.offset -= sizeof(struct short_ad);
 176                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 177                                epos.offset -= sizeof(struct long_ad);
 178                } else
 179                        offset = 0;
 180
 181                fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
 182                if (!fibh->sbh)
 183                        goto out_err;
 184        }
 185
 186        fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 187        if (!fname)
 188                goto out_err;
 189
 190        while (f_pos < size) {
 191                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
 192                                        &elen, &offset);
 193                if (!fi)
 194                        goto out_err;
 195
 196                liu = le16_to_cpu(cfi->lengthOfImpUse);
 197                lfi = cfi->lengthFileIdent;
 198
 199                if (fibh->sbh == fibh->ebh) {
 200                        nameptr = fi->fileIdent + liu;
 201                } else {
 202                        int poffset;    /* Unpaded ending offset */
 203
 204                        poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
 205                                        liu + lfi;
 206
 207                        if (poffset >= lfi)
 208                                nameptr = (uint8_t *)(fibh->ebh->b_data +
 209                                                      poffset - lfi);
 210                        else {
 211                                nameptr = fname;
 212                                memcpy(nameptr, fi->fileIdent + liu,
 213                                        lfi - poffset);
 214                                memcpy(nameptr + lfi - poffset,
 215                                        fibh->ebh->b_data, poffset);
 216                        }
 217                }
 218
 219                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
 220                        if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE))
 221                                continue;
 222                }
 223
 224                if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) {
 225                        if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE))
 226                                continue;
 227                }
 228
 229                if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
 230                    isdotdot)
 231                        goto out_ok;
 232
 233                if (!lfi)
 234                        continue;
 235
 236                flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
 237                if (flen && udf_match(flen, fname, child->len, child->name))
 238                        goto out_ok;
 239        }
 240
 241out_err:
 242        fi = NULL;
 243        if (fibh->sbh != fibh->ebh)
 244                brelse(fibh->ebh);
 245        brelse(fibh->sbh);
 246out_ok:
 247        brelse(epos.bh);
 248        kfree(fname);
 249
 250        return fi;
 251}
 252
 253static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
 254                                 unsigned int flags)
 255{
 256        struct inode *inode = NULL;
 257        struct fileIdentDesc cfi;
 258        struct udf_fileident_bh fibh;
 259
 260        if (dentry->d_name.len > UDF_NAME_LEN - 2)
 261                return ERR_PTR(-ENAMETOOLONG);
 262
 263#ifdef UDF_RECOVERY
 264        /* temporary shorthand for specifying files by inode number */
 265        if (!strncmp(dentry->d_name.name, ".B=", 3)) {
 266                struct kernel_lb_addr lb = {
 267                        .logicalBlockNum = 0,
 268                        .partitionReferenceNum =
 269                                simple_strtoul(dentry->d_name.name + 3,
 270                                                NULL, 0),
 271                };
 272                inode = udf_iget(dir->i_sb, lb);
 273                if (!inode) {
 274                        return ERR_PTR(-EACCES);
 275                }
 276        } else
 277#endif /* UDF_RECOVERY */
 278
 279        if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) {
 280                struct kernel_lb_addr loc;
 281
 282                if (fibh.sbh != fibh.ebh)
 283                        brelse(fibh.ebh);
 284                brelse(fibh.sbh);
 285
 286                loc = lelb_to_cpu(cfi.icb.extLocation);
 287                inode = udf_iget(dir->i_sb, &loc);
 288                if (!inode) {
 289                        return ERR_PTR(-EACCES);
 290                }
 291        }
 292
 293        return d_splice_alias(inode, dentry);
 294}
 295
 296static struct fileIdentDesc *udf_add_entry(struct inode *dir,
 297                                           struct dentry *dentry,
 298                                           struct udf_fileident_bh *fibh,
 299                                           struct fileIdentDesc *cfi, int *err)
 300{
 301        struct super_block *sb = dir->i_sb;
 302        struct fileIdentDesc *fi = NULL;
 303        unsigned char *name = NULL;
 304        int namelen;
 305        loff_t f_pos;
 306        loff_t size = udf_ext0_offset(dir) + dir->i_size;
 307        int nfidlen;
 308        uint8_t lfi;
 309        uint16_t liu;
 310        int block;
 311        struct kernel_lb_addr eloc;
 312        uint32_t elen = 0;
 313        sector_t offset;
 314        struct extent_position epos = {};
 315        struct udf_inode_info *dinfo;
 316
 317        fibh->sbh = fibh->ebh = NULL;
 318        name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 319        if (!name) {
 320                *err = -ENOMEM;
 321                goto out_err;
 322        }
 323
 324        if (dentry) {
 325                if (!dentry->d_name.len) {
 326                        *err = -EINVAL;
 327                        goto out_err;
 328                }
 329                namelen = udf_put_filename(sb, dentry->d_name.name, name,
 330                                                 dentry->d_name.len);
 331                if (!namelen) {
 332                        *err = -ENAMETOOLONG;
 333                        goto out_err;
 334                }
 335        } else {
 336                namelen = 0;
 337        }
 338
 339        nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3;
 340
 341        f_pos = udf_ext0_offset(dir);
 342
 343        fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
 344        dinfo = UDF_I(dir);
 345        if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
 346                if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
 347                    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
 348                        block = udf_get_lb_pblock(dir->i_sb,
 349                                        &dinfo->i_location, 0);
 350                        fibh->soffset = fibh->eoffset = sb->s_blocksize;
 351                        goto add;
 352                }
 353                block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
 354                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
 355                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 356                                epos.offset -= sizeof(struct short_ad);
 357                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 358                                epos.offset -= sizeof(struct long_ad);
 359                } else
 360                        offset = 0;
 361
 362                fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
 363                if (!fibh->sbh) {
 364                        *err = -EIO;
 365                        goto out_err;
 366                }
 367
 368                block = dinfo->i_location.logicalBlockNum;
 369        }
 370
 371        while (f_pos < size) {
 372                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
 373                                        &elen, &offset);
 374
 375                if (!fi) {
 376                        *err = -EIO;
 377                        goto out_err;
 378                }
 379
 380                liu = le16_to_cpu(cfi->lengthOfImpUse);
 381                lfi = cfi->lengthFileIdent;
 382
 383                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
 384                        if (((sizeof(struct fileIdentDesc) +
 385                                        liu + lfi + 3) & ~3) == nfidlen) {
 386                                cfi->descTag.tagSerialNum = cpu_to_le16(1);
 387                                cfi->fileVersionNum = cpu_to_le16(1);
 388                                cfi->fileCharacteristics = 0;
 389                                cfi->lengthFileIdent = namelen;
 390                                cfi->lengthOfImpUse = cpu_to_le16(0);
 391                                if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
 392                                                  name))
 393                                        goto out_ok;
 394                                else {
 395                                        *err = -EIO;
 396                                        goto out_err;
 397                                }
 398                        }
 399                }
 400        }
 401
 402add:
 403        f_pos += nfidlen;
 404
 405        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
 406            sb->s_blocksize - fibh->eoffset < nfidlen) {
 407                brelse(epos.bh);
 408                epos.bh = NULL;
 409                fibh->soffset -= udf_ext0_offset(dir);
 410                fibh->eoffset -= udf_ext0_offset(dir);
 411                f_pos -= udf_ext0_offset(dir);
 412                if (fibh->sbh != fibh->ebh)
 413                        brelse(fibh->ebh);
 414                brelse(fibh->sbh);
 415                fibh->sbh = fibh->ebh =
 416                                udf_expand_dir_adinicb(dir, &block, err);
 417                if (!fibh->sbh)
 418                        goto out_err;
 419                epos.block = dinfo->i_location;
 420                epos.offset = udf_file_entry_alloc_offset(dir);
 421                /* Load extent udf_expand_dir_adinicb() has created */
 422                udf_current_aext(dir, &epos, &eloc, &elen, 1);
 423        }
 424
 425        /* Entry fits into current block? */
 426        if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
 427                fibh->soffset = fibh->eoffset;
 428                fibh->eoffset += nfidlen;
 429                if (fibh->sbh != fibh->ebh) {
 430                        brelse(fibh->sbh);
 431                        fibh->sbh = fibh->ebh;
 432                }
 433
 434                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
 435                        block = dinfo->i_location.logicalBlockNum;
 436                        fi = (struct fileIdentDesc *)
 437                                        (dinfo->i_ext.i_data +
 438                                         fibh->soffset -
 439                                         udf_ext0_offset(dir) +
 440                                         dinfo->i_lenEAttr);
 441                } else {
 442                        block = eloc.logicalBlockNum +
 443                                        ((elen - 1) >>
 444                                                dir->i_sb->s_blocksize_bits);
 445                        fi = (struct fileIdentDesc *)
 446                                (fibh->sbh->b_data + fibh->soffset);
 447                }
 448        } else {
 449                /* Round up last extent in the file */
 450                elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
 451                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 452                        epos.offset -= sizeof(struct short_ad);
 453                else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 454                        epos.offset -= sizeof(struct long_ad);
 455                udf_write_aext(dir, &epos, &eloc, elen, 1);
 456                dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize
 457                                        - 1) & ~(sb->s_blocksize - 1);
 458
 459                fibh->soffset = fibh->eoffset - sb->s_blocksize;
 460                fibh->eoffset += nfidlen - sb->s_blocksize;
 461                if (fibh->sbh != fibh->ebh) {
 462                        brelse(fibh->sbh);
 463                        fibh->sbh = fibh->ebh;
 464                }
 465
 466                block = eloc.logicalBlockNum + ((elen - 1) >>
 467                                                dir->i_sb->s_blocksize_bits);
 468                fibh->ebh = udf_bread(dir,
 469                                f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
 470                if (!fibh->ebh)
 471                        goto out_err;
 472                /* Extents could have been merged, invalidate our position */
 473                brelse(epos.bh);
 474                epos.bh = NULL;
 475                epos.block = dinfo->i_location;
 476                epos.offset = udf_file_entry_alloc_offset(dir);
 477
 478                if (!fibh->soffset) {
 479                        /* Find the freshly allocated block */
 480                        while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
 481                                (EXT_RECORDED_ALLOCATED >> 30))
 482                                ;
 483                        block = eloc.logicalBlockNum + ((elen - 1) >>
 484                                        dir->i_sb->s_blocksize_bits);
 485                        brelse(fibh->sbh);
 486                        fibh->sbh = fibh->ebh;
 487                        fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
 488                } else {
 489                        fi = (struct fileIdentDesc *)
 490                                (fibh->sbh->b_data + sb->s_blocksize +
 491                                        fibh->soffset);
 492                }
 493        }
 494
 495        memset(cfi, 0, sizeof(struct fileIdentDesc));
 496        if (UDF_SB(sb)->s_udfrev >= 0x0200)
 497                udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block,
 498                            sizeof(struct tag));
 499        else
 500                udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block,
 501                            sizeof(struct tag));
 502        cfi->fileVersionNum = cpu_to_le16(1);
 503        cfi->lengthFileIdent = namelen;
 504        cfi->lengthOfImpUse = cpu_to_le16(0);
 505        if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
 506                dir->i_size += nfidlen;
 507                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 508                        dinfo->i_lenAlloc += nfidlen;
 509                else {
 510                        /* Find the last extent and truncate it to proper size */
 511                        while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
 512                                (EXT_RECORDED_ALLOCATED >> 30))
 513                                ;
 514                        elen -= dinfo->i_lenExtents - dir->i_size;
 515                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 516                                epos.offset -= sizeof(struct short_ad);
 517                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 518                                epos.offset -= sizeof(struct long_ad);
 519                        udf_write_aext(dir, &epos, &eloc, elen, 1);
 520                        dinfo->i_lenExtents = dir->i_size;
 521                }
 522
 523                mark_inode_dirty(dir);
 524                goto out_ok;
 525        } else {
 526                *err = -EIO;
 527                goto out_err;
 528        }
 529
 530out_err:
 531        fi = NULL;
 532        if (fibh->sbh != fibh->ebh)
 533                brelse(fibh->ebh);
 534        brelse(fibh->sbh);
 535out_ok:
 536        brelse(epos.bh);
 537        kfree(name);
 538        return fi;
 539}
 540
 541static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
 542                            struct udf_fileident_bh *fibh,
 543                            struct fileIdentDesc *cfi)
 544{
 545        cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED;
 546
 547        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
 548                memset(&(cfi->icb), 0x00, sizeof(struct long_ad));
 549
 550        return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
 551}
 552
 553static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 554                      bool excl)
 555{
 556        struct udf_fileident_bh fibh;
 557        struct inode *inode;
 558        struct fileIdentDesc cfi, *fi;
 559        int err;
 560        struct udf_inode_info *iinfo;
 561
 562        inode = udf_new_inode(dir, mode, &err);
 563        if (!inode) {
 564                return err;
 565        }
 566
 567        iinfo = UDF_I(inode);
 568        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 569                inode->i_data.a_ops = &udf_adinicb_aops;
 570        else
 571                inode->i_data.a_ops = &udf_aops;
 572        inode->i_op = &udf_file_inode_operations;
 573        inode->i_fop = &udf_file_operations;
 574        mark_inode_dirty(inode);
 575
 576        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 577        if (!fi) {
 578                inode_dec_link_count(inode);
 579                iput(inode);
 580                return err;
 581        }
 582        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 583        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 584        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 585                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
 586        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 587        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 588                mark_inode_dirty(dir);
 589        if (fibh.sbh != fibh.ebh)
 590                brelse(fibh.ebh);
 591        brelse(fibh.sbh);
 592        d_instantiate(dentry, inode);
 593
 594        return 0;
 595}
 596
 597static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
 598{
 599        struct inode *inode;
 600        struct udf_inode_info *iinfo;
 601        int err;
 602
 603        inode = udf_new_inode(dir, mode, &err);
 604        if (!inode)
 605                return err;
 606
 607        iinfo = UDF_I(inode);
 608        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 609                inode->i_data.a_ops = &udf_adinicb_aops;
 610        else
 611                inode->i_data.a_ops = &udf_aops;
 612        inode->i_op = &udf_file_inode_operations;
 613        inode->i_fop = &udf_file_operations;
 614        mark_inode_dirty(inode);
 615
 616        d_tmpfile(dentry, inode);
 617        return 0;
 618}
 619
 620static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
 621                     dev_t rdev)
 622{
 623        struct inode *inode;
 624        struct udf_fileident_bh fibh;
 625        struct fileIdentDesc cfi, *fi;
 626        int err;
 627        struct udf_inode_info *iinfo;
 628
 629        if (!old_valid_dev(rdev))
 630                return -EINVAL;
 631
 632        err = -EIO;
 633        inode = udf_new_inode(dir, mode, &err);
 634        if (!inode)
 635                goto out;
 636
 637        iinfo = UDF_I(inode);
 638        init_special_inode(inode, mode, rdev);
 639        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 640        if (!fi) {
 641                inode_dec_link_count(inode);
 642                iput(inode);
 643                return err;
 644        }
 645        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 646        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 647        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 648                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
 649        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 650        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 651                mark_inode_dirty(dir);
 652        mark_inode_dirty(inode);
 653
 654        if (fibh.sbh != fibh.ebh)
 655                brelse(fibh.ebh);
 656        brelse(fibh.sbh);
 657        d_instantiate(dentry, inode);
 658        err = 0;
 659
 660out:
 661        return err;
 662}
 663
 664static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 665{
 666        struct inode *inode;
 667        struct udf_fileident_bh fibh;
 668        struct fileIdentDesc cfi, *fi;
 669        int err;
 670        struct udf_inode_info *dinfo = UDF_I(dir);
 671        struct udf_inode_info *iinfo;
 672
 673        err = -EIO;
 674        inode = udf_new_inode(dir, S_IFDIR | mode, &err);
 675        if (!inode)
 676                goto out;
 677
 678        iinfo = UDF_I(inode);
 679        inode->i_op = &udf_dir_inode_operations;
 680        inode->i_fop = &udf_dir_operations;
 681        fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
 682        if (!fi) {
 683                inode_dec_link_count(inode);
 684                iput(inode);
 685                goto out;
 686        }
 687        set_nlink(inode, 2);
 688        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 689        cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
 690        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 691                cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL);
 692        cfi.fileCharacteristics =
 693                        FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
 694        udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
 695        brelse(fibh.sbh);
 696        mark_inode_dirty(inode);
 697
 698        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 699        if (!fi) {
 700                clear_nlink(inode);
 701                mark_inode_dirty(inode);
 702                iput(inode);
 703                goto out;
 704        }
 705        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 706        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 707        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 708                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
 709        cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
 710        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 711        inc_nlink(dir);
 712        mark_inode_dirty(dir);
 713        d_instantiate(dentry, inode);
 714        if (fibh.sbh != fibh.ebh)
 715                brelse(fibh.ebh);
 716        brelse(fibh.sbh);
 717        err = 0;
 718
 719out:
 720        return err;
 721}
 722
 723static int empty_dir(struct inode *dir)
 724{
 725        struct fileIdentDesc *fi, cfi;
 726        struct udf_fileident_bh fibh;
 727        loff_t f_pos;
 728        loff_t size = udf_ext0_offset(dir) + dir->i_size;
 729        int block;
 730        struct kernel_lb_addr eloc;
 731        uint32_t elen;
 732        sector_t offset;
 733        struct extent_position epos = {};
 734        struct udf_inode_info *dinfo = UDF_I(dir);
 735
 736        f_pos = udf_ext0_offset(dir);
 737        fibh.soffset = fibh.eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
 738
 739        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 740                fibh.sbh = fibh.ebh = NULL;
 741        else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
 742                              &epos, &eloc, &elen, &offset) ==
 743                                        (EXT_RECORDED_ALLOCATED >> 30)) {
 744                block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
 745                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
 746                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 747                                epos.offset -= sizeof(struct short_ad);
 748                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 749                                epos.offset -= sizeof(struct long_ad);
 750                } else
 751                        offset = 0;
 752
 753                fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block);
 754                if (!fibh.sbh) {
 755                        brelse(epos.bh);
 756                        return 0;
 757                }
 758        } else {
 759                brelse(epos.bh);
 760                return 0;
 761        }
 762
 763        while (f_pos < size) {
 764                fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc,
 765                                        &elen, &offset);
 766                if (!fi) {
 767                        if (fibh.sbh != fibh.ebh)
 768                                brelse(fibh.ebh);
 769                        brelse(fibh.sbh);
 770                        brelse(epos.bh);
 771                        return 0;
 772                }
 773
 774                if (cfi.lengthFileIdent &&
 775                    (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) {
 776                        if (fibh.sbh != fibh.ebh)
 777                                brelse(fibh.ebh);
 778                        brelse(fibh.sbh);
 779                        brelse(epos.bh);
 780                        return 0;
 781                }
 782        }
 783
 784        if (fibh.sbh != fibh.ebh)
 785                brelse(fibh.ebh);
 786        brelse(fibh.sbh);
 787        brelse(epos.bh);
 788
 789        return 1;
 790}
 791
 792static int udf_rmdir(struct inode *dir, struct dentry *dentry)
 793{
 794        int retval;
 795        struct inode *inode = dentry->d_inode;
 796        struct udf_fileident_bh fibh;
 797        struct fileIdentDesc *fi, cfi;
 798        struct kernel_lb_addr tloc;
 799
 800        retval = -ENOENT;
 801        fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
 802        if (!fi)
 803                goto out;
 804
 805        retval = -EIO;
 806        tloc = lelb_to_cpu(cfi.icb.extLocation);
 807        if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
 808                goto end_rmdir;
 809        retval = -ENOTEMPTY;
 810        if (!empty_dir(inode))
 811                goto end_rmdir;
 812        retval = udf_delete_entry(dir, fi, &fibh, &cfi);
 813        if (retval)
 814                goto end_rmdir;
 815        if (inode->i_nlink != 2)
 816                udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)\n",
 817                         inode->i_nlink);
 818        clear_nlink(inode);
 819        inode->i_size = 0;
 820        inode_dec_link_count(dir);
 821        inode->i_ctime = dir->i_ctime = dir->i_mtime =
 822                                                current_fs_time(dir->i_sb);
 823        mark_inode_dirty(dir);
 824
 825end_rmdir:
 826        if (fibh.sbh != fibh.ebh)
 827                brelse(fibh.ebh);
 828        brelse(fibh.sbh);
 829
 830out:
 831        return retval;
 832}
 833
 834static int udf_unlink(struct inode *dir, struct dentry *dentry)
 835{
 836        int retval;
 837        struct inode *inode = dentry->d_inode;
 838        struct udf_fileident_bh fibh;
 839        struct fileIdentDesc *fi;
 840        struct fileIdentDesc cfi;
 841        struct kernel_lb_addr tloc;
 842
 843        retval = -ENOENT;
 844        fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
 845        if (!fi)
 846                goto out;
 847
 848        retval = -EIO;
 849        tloc = lelb_to_cpu(cfi.icb.extLocation);
 850        if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
 851                goto end_unlink;
 852
 853        if (!inode->i_nlink) {
 854                udf_debug("Deleting nonexistent file (%lu), %d\n",
 855                          inode->i_ino, inode->i_nlink);
 856                set_nlink(inode, 1);
 857        }
 858        retval = udf_delete_entry(dir, fi, &fibh, &cfi);
 859        if (retval)
 860                goto end_unlink;
 861        dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
 862        mark_inode_dirty(dir);
 863        inode_dec_link_count(inode);
 864        inode->i_ctime = dir->i_ctime;
 865        retval = 0;
 866
 867end_unlink:
 868        if (fibh.sbh != fibh.ebh)
 869                brelse(fibh.ebh);
 870        brelse(fibh.sbh);
 871
 872out:
 873        return retval;
 874}
 875
 876static int udf_symlink(struct inode *dir, struct dentry *dentry,
 877                       const char *symname)
 878{
 879        struct inode *inode;
 880        struct pathComponent *pc;
 881        const char *compstart;
 882        struct udf_fileident_bh fibh;
 883        struct extent_position epos = {};
 884        int eoffset, elen = 0;
 885        struct fileIdentDesc *fi;
 886        struct fileIdentDesc cfi;
 887        uint8_t *ea;
 888        int err;
 889        int block;
 890        unsigned char *name = NULL;
 891        int namelen;
 892        struct udf_inode_info *iinfo;
 893        struct super_block *sb = dir->i_sb;
 894
 895        inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
 896        if (!inode)
 897                goto out;
 898
 899        iinfo = UDF_I(inode);
 900        down_write(&iinfo->i_data_sem);
 901        name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 902        if (!name) {
 903                err = -ENOMEM;
 904                goto out_no_entry;
 905        }
 906
 907        inode->i_data.a_ops = &udf_symlink_aops;
 908        inode->i_op = &udf_symlink_inode_operations;
 909
 910        if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
 911                struct kernel_lb_addr eloc;
 912                uint32_t bsize;
 913
 914                block = udf_new_block(sb, inode,
 915                                iinfo->i_location.partitionReferenceNum,
 916                                iinfo->i_location.logicalBlockNum, &err);
 917                if (!block)
 918                        goto out_no_entry;
 919                epos.block = iinfo->i_location;
 920                epos.offset = udf_file_entry_alloc_offset(inode);
 921                epos.bh = NULL;
 922                eloc.logicalBlockNum = block;
 923                eloc.partitionReferenceNum =
 924                                iinfo->i_location.partitionReferenceNum;
 925                bsize = sb->s_blocksize;
 926                iinfo->i_lenExtents = bsize;
 927                udf_add_aext(inode, &epos, &eloc, bsize, 0);
 928                brelse(epos.bh);
 929
 930                block = udf_get_pblock(sb, block,
 931                                iinfo->i_location.partitionReferenceNum,
 932                                0);
 933                epos.bh = udf_tgetblk(sb, block);
 934                lock_buffer(epos.bh);
 935                memset(epos.bh->b_data, 0x00, bsize);
 936                set_buffer_uptodate(epos.bh);
 937                unlock_buffer(epos.bh);
 938                mark_buffer_dirty_inode(epos.bh, inode);
 939                ea = epos.bh->b_data + udf_ext0_offset(inode);
 940        } else
 941                ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
 942
 943        eoffset = sb->s_blocksize - udf_ext0_offset(inode);
 944        pc = (struct pathComponent *)ea;
 945
 946        if (*symname == '/') {
 947                do {
 948                        symname++;
 949                } while (*symname == '/');
 950
 951                pc->componentType = 1;
 952                pc->lengthComponentIdent = 0;
 953                pc->componentFileVersionNum = 0;
 954                elen += sizeof(struct pathComponent);
 955        }
 956
 957        err = -ENAMETOOLONG;
 958
 959        while (*symname) {
 960                if (elen + sizeof(struct pathComponent) > eoffset)
 961                        goto out_no_entry;
 962
 963                pc = (struct pathComponent *)(ea + elen);
 964
 965                compstart = symname;
 966
 967                do {
 968                        symname++;
 969                } while (*symname && *symname != '/');
 970
 971                pc->componentType = 5;
 972                pc->lengthComponentIdent = 0;
 973                pc->componentFileVersionNum = 0;
 974                if (compstart[0] == '.') {
 975                        if ((symname - compstart) == 1)
 976                                pc->componentType = 4;
 977                        else if ((symname - compstart) == 2 &&
 978                                        compstart[1] == '.')
 979                                pc->componentType = 3;
 980                }
 981
 982                if (pc->componentType == 5) {
 983                        namelen = udf_put_filename(sb, compstart, name,
 984                                                   symname - compstart);
 985                        if (!namelen)
 986                                goto out_no_entry;
 987
 988                        if (elen + sizeof(struct pathComponent) + namelen >
 989                                        eoffset)
 990                                goto out_no_entry;
 991                        else
 992                                pc->lengthComponentIdent = namelen;
 993
 994                        memcpy(pc->componentIdent, name, namelen);
 995                }
 996
 997                elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
 998
 999                if (*symname) {
1000                        do {
1001                                symname++;
1002                        } while (*symname == '/');
1003                }
1004        }
1005
1006        brelse(epos.bh);
1007        inode->i_size = elen;
1008        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1009                iinfo->i_lenAlloc = inode->i_size;
1010        else
1011                udf_truncate_tail_extent(inode);
1012        mark_inode_dirty(inode);
1013
1014        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
1015        if (!fi)
1016                goto out_no_entry;
1017        cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
1018        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
1019        if (UDF_SB(inode->i_sb)->s_lvid_bh) {
1020                *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
1021                        cpu_to_le32(lvid_get_unique_id(sb));
1022        }
1023        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
1024        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1025                mark_inode_dirty(dir);
1026        up_write(&iinfo->i_data_sem);
1027        if (fibh.sbh != fibh.ebh)
1028                brelse(fibh.ebh);
1029        brelse(fibh.sbh);
1030        d_instantiate(dentry, inode);
1031        err = 0;
1032
1033out:
1034        kfree(name);
1035        return err;
1036
1037out_no_entry:
1038        up_write(&iinfo->i_data_sem);
1039        inode_dec_link_count(inode);
1040        iput(inode);
1041        goto out;
1042}
1043
1044static int udf_link(struct dentry *old_dentry, struct inode *dir,
1045                    struct dentry *dentry)
1046{
1047        struct inode *inode = old_dentry->d_inode;
1048        struct udf_fileident_bh fibh;
1049        struct fileIdentDesc cfi, *fi;
1050        int err;
1051
1052        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
1053        if (!fi) {
1054                return err;
1055        }
1056        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
1057        cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
1058        if (UDF_SB(inode->i_sb)->s_lvid_bh) {
1059                *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
1060                        cpu_to_le32(lvid_get_unique_id(inode->i_sb));
1061        }
1062        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
1063        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1064                mark_inode_dirty(dir);
1065
1066        if (fibh.sbh != fibh.ebh)
1067                brelse(fibh.ebh);
1068        brelse(fibh.sbh);
1069        inc_nlink(inode);
1070        inode->i_ctime = current_fs_time(inode->i_sb);
1071        mark_inode_dirty(inode);
1072        ihold(inode);
1073        d_instantiate(dentry, inode);
1074
1075        return 0;
1076}
1077
1078/* Anybody can rename anything with this: the permission checks are left to the
1079 * higher-level routines.
1080 */
1081static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
1082                      struct inode *new_dir, struct dentry *new_dentry)
1083{
1084        struct inode *old_inode = old_dentry->d_inode;
1085        struct inode *new_inode = new_dentry->d_inode;
1086        struct udf_fileident_bh ofibh, nfibh;
1087        struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL;
1088        struct fileIdentDesc ocfi, ncfi;
1089        struct buffer_head *dir_bh = NULL;
1090        int retval = -ENOENT;
1091        struct kernel_lb_addr tloc;
1092        struct udf_inode_info *old_iinfo = UDF_I(old_inode);
1093
1094        ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
1095        if (ofi) {
1096                if (ofibh.sbh != ofibh.ebh)
1097                        brelse(ofibh.ebh);
1098                brelse(ofibh.sbh);
1099        }
1100        tloc = lelb_to_cpu(ocfi.icb.extLocation);
1101        if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0)
1102            != old_inode->i_ino)
1103                goto end_rename;
1104
1105        nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi);
1106        if (nfi) {
1107                if (!new_inode) {
1108                        if (nfibh.sbh != nfibh.ebh)
1109                                brelse(nfibh.ebh);
1110                        brelse(nfibh.sbh);
1111                        nfi = NULL;
1112                }
1113        }
1114        if (S_ISDIR(old_inode->i_mode)) {
1115                int offset = udf_ext0_offset(old_inode);
1116
1117                if (new_inode) {
1118                        retval = -ENOTEMPTY;
1119                        if (!empty_dir(new_inode))
1120                                goto end_rename;
1121                }
1122                retval = -EIO;
1123                if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
1124                        dir_fi = udf_get_fileident(
1125                                        old_iinfo->i_ext.i_data -
1126                                          (old_iinfo->i_efe ?
1127                                           sizeof(struct extendedFileEntry) :
1128                                           sizeof(struct fileEntry)),
1129                                        old_inode->i_sb->s_blocksize, &offset);
1130                } else {
1131                        dir_bh = udf_bread(old_inode, 0, 0, &retval);
1132                        if (!dir_bh)
1133                                goto end_rename;
1134                        dir_fi = udf_get_fileident(dir_bh->b_data,
1135                                        old_inode->i_sb->s_blocksize, &offset);
1136                }
1137                if (!dir_fi)
1138                        goto end_rename;
1139                tloc = lelb_to_cpu(dir_fi->icb.extLocation);
1140                if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
1141                                old_dir->i_ino)
1142                        goto end_rename;
1143        }
1144        if (!nfi) {
1145                nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi,
1146                                    &retval);
1147                if (!nfi)
1148                        goto end_rename;
1149        }
1150
1151        /*
1152         * Like most other Unix systems, set the ctime for inodes on a
1153         * rename.
1154         */
1155        old_inode->i_ctime = current_fs_time(old_inode->i_sb);
1156        mark_inode_dirty(old_inode);
1157
1158        /*
1159         * ok, that's it
1160         */
1161        ncfi.fileVersionNum = ocfi.fileVersionNum;
1162        ncfi.fileCharacteristics = ocfi.fileCharacteristics;
1163        memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(struct long_ad));
1164        udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);
1165
1166        /* The old fid may have moved - find it again */
1167        ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
1168        udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
1169
1170        if (new_inode) {
1171                new_inode->i_ctime = current_fs_time(new_inode->i_sb);
1172                inode_dec_link_count(new_inode);
1173        }
1174        old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
1175        mark_inode_dirty(old_dir);
1176
1177        if (dir_fi) {
1178                dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
1179                udf_update_tag((char *)dir_fi,
1180                                (sizeof(struct fileIdentDesc) +
1181                                le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
1182                if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1183                        mark_inode_dirty(old_inode);
1184                else
1185                        mark_buffer_dirty_inode(dir_bh, old_inode);
1186
1187                inode_dec_link_count(old_dir);
1188                if (new_inode)
1189                        inode_dec_link_count(new_inode);
1190                else {
1191                        inc_nlink(new_dir);
1192                        mark_inode_dirty(new_dir);
1193                }
1194        }
1195
1196        if (ofi) {
1197                if (ofibh.sbh != ofibh.ebh)
1198                        brelse(ofibh.ebh);
1199                brelse(ofibh.sbh);
1200        }
1201
1202        retval = 0;
1203
1204end_rename:
1205        brelse(dir_bh);
1206        if (nfi) {
1207                if (nfibh.sbh != nfibh.ebh)
1208                        brelse(nfibh.ebh);
1209                brelse(nfibh.sbh);
1210        }
1211
1212        return retval;
1213}
1214
1215static struct dentry *udf_get_parent(struct dentry *child)
1216{
1217        struct kernel_lb_addr tloc;
1218        struct inode *inode = NULL;
1219        struct qstr dotdot = QSTR_INIT("..", 2);
1220        struct fileIdentDesc cfi;
1221        struct udf_fileident_bh fibh;
1222
1223        if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
1224                goto out_unlock;
1225
1226        if (fibh.sbh != fibh.ebh)
1227                brelse(fibh.ebh);
1228        brelse(fibh.sbh);
1229
1230        tloc = lelb_to_cpu(cfi.icb.extLocation);
1231        inode = udf_iget(child->d_inode->i_sb, &tloc);
1232        if (!inode)
1233                goto out_unlock;
1234
1235        return d_obtain_alias(inode);
1236out_unlock:
1237        return ERR_PTR(-EACCES);
1238}
1239
1240
1241static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
1242                                        u16 partref, __u32 generation)
1243{
1244        struct inode *inode;
1245        struct kernel_lb_addr loc;
1246
1247        if (block == 0)
1248                return ERR_PTR(-ESTALE);
1249
1250        loc.logicalBlockNum = block;
1251        loc.partitionReferenceNum = partref;
1252        inode = udf_iget(sb, &loc);
1253
1254        if (inode == NULL)
1255                return ERR_PTR(-ENOMEM);
1256
1257        if (generation && inode->i_generation != generation) {
1258                iput(inode);
1259                return ERR_PTR(-ESTALE);
1260        }
1261        return d_obtain_alias(inode);
1262}
1263
1264static struct dentry *udf_fh_to_dentry(struct super_block *sb,
1265                                       struct fid *fid, int fh_len, int fh_type)
1266{
1267        if ((fh_len != 3 && fh_len != 5) ||
1268            (fh_type != FILEID_UDF_WITH_PARENT &&
1269             fh_type != FILEID_UDF_WITHOUT_PARENT))
1270                return NULL;
1271
1272        return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
1273                        fid->udf.generation);
1274}
1275
1276static struct dentry *udf_fh_to_parent(struct super_block *sb,
1277                                       struct fid *fid, int fh_len, int fh_type)
1278{
1279        if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT)
1280                return NULL;
1281
1282        return udf_nfs_get_inode(sb, fid->udf.parent_block,
1283                                 fid->udf.parent_partref,
1284                                 fid->udf.parent_generation);
1285}
1286static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
1287                         struct inode *parent)
1288{
1289        int len = *lenp;
1290        struct kernel_lb_addr location = UDF_I(inode)->i_location;
1291        struct fid *fid = (struct fid *)fh;
1292        int type = FILEID_UDF_WITHOUT_PARENT;
1293
1294        if (parent && (len < 5)) {
1295                *lenp = 5;
1296                return FILEID_INVALID;
1297        } else if (len < 3) {
1298                *lenp = 3;
1299                return FILEID_INVALID;
1300        }
1301
1302        *lenp = 3;
1303        fid->udf.block = location.logicalBlockNum;
1304        fid->udf.partref = location.partitionReferenceNum;
1305        fid->udf.parent_partref = 0;
1306        fid->udf.generation = inode->i_generation;
1307
1308        if (parent) {
1309                location = UDF_I(parent)->i_location;
1310                fid->udf.parent_block = location.logicalBlockNum;
1311                fid->udf.parent_partref = location.partitionReferenceNum;
1312                fid->udf.parent_generation = inode->i_generation;
1313                *lenp = 5;
1314                type = FILEID_UDF_WITH_PARENT;
1315        }
1316
1317        return type;
1318}
1319
1320const struct export_operations udf_export_ops = {
1321        .encode_fh      = udf_encode_fh,
1322        .fh_to_dentry   = udf_fh_to_dentry,
1323        .fh_to_parent   = udf_fh_to_parent,
1324        .get_parent     = udf_get_parent,
1325};
1326
1327const struct inode_operations udf_dir_inode_operations = {
1328        .lookup                         = udf_lookup,
1329        .create                         = udf_create,
1330        .link                           = udf_link,
1331        .unlink                         = udf_unlink,
1332        .symlink                        = udf_symlink,
1333        .mkdir                          = udf_mkdir,
1334        .rmdir                          = udf_rmdir,
1335        .mknod                          = udf_mknod,
1336        .rename                         = udf_rename,
1337        .tmpfile                        = udf_tmpfile,
1338};
1339const struct inode_operations udf_symlink_inode_operations = {
1340        .readlink       = generic_readlink,
1341        .follow_link    = page_follow_link_light,
1342        .put_link       = page_put_link,
1343};
1344
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.