~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/udf/namei.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.