|
|
1.1 ! root 1: /* fsys_xfs.c - an implementation for the SGI XFS file system */ ! 2: /* ! 3: * GRUB -- GRand Unified Bootloader ! 4: * Copyright (C) 2001,2002 Free Software Foundation, Inc. ! 5: * ! 6: * This program is free software; you can redistribute it and/or modify ! 7: * it under the terms of the GNU General Public License as published by ! 8: * the Free Software Foundation; either version 2 of the License, or ! 9: * (at your option) any later version. ! 10: * ! 11: * This program is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: * GNU General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU General Public License ! 17: * along with this program; if not, write to the Free Software ! 18: * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, ! 19: * MA 02110-1301, USA. ! 20: */ ! 21: ! 22: #ifdef FSYS_XFS ! 23: ! 24: #include "shared.h" ! 25: #include "filesys.h" ! 26: #include "xfs.h" ! 27: ! 28: #define MAX_LINK_COUNT 8 ! 29: ! 30: typedef struct xad { ! 31: xfs_fileoff_t offset; ! 32: xfs_fsblock_t start; ! 33: xfs_filblks_t len; ! 34: } xad_t; ! 35: ! 36: struct xfs_info { ! 37: int bsize; ! 38: int dirbsize; ! 39: int isize; ! 40: unsigned int agblocks; ! 41: int bdlog; ! 42: int blklog; ! 43: int inopblog; ! 44: int agblklog; ! 45: int agnolog; ! 46: unsigned int nextents; ! 47: xfs_daddr_t next; ! 48: xfs_daddr_t daddr; ! 49: xfs_dablk_t forw; ! 50: xfs_dablk_t dablk; ! 51: xfs_bmbt_rec_32_t *xt; ! 52: xfs_bmbt_ptr_t ptr0; ! 53: int btnode_ptr0_off; ! 54: int i8param; ! 55: int dirpos; ! 56: int dirmax; ! 57: int blkoff; ! 58: int fpos; ! 59: xfs_ino_t rootino; ! 60: }; ! 61: ! 62: static struct xfs_info xfs; ! 63: ! 64: #define dirbuf ((char *)FSYS_BUF) ! 65: #define filebuf ((char *)FSYS_BUF + 4096) ! 66: #define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192)) ! 67: #define icore (inode->di_core) ! 68: ! 69: #define mask32lo(n) (((__uint32_t)1 << (n)) - 1) ! 70: ! 71: #define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1)) ! 72: #define XFS_INO_OFFSET_BITS xfs.inopblog ! 73: #define XFS_INO_AGBNO_BITS xfs.agblklog ! 74: #define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog) ! 75: #define XFS_INO_AGNO_BITS xfs.agnolog ! 76: ! 77: static inline xfs_agblock_t ! 78: agino2agbno (xfs_agino_t agino) ! 79: { ! 80: return agino >> XFS_INO_OFFSET_BITS; ! 81: } ! 82: ! 83: static inline xfs_agnumber_t ! 84: ino2agno (xfs_ino_t ino) ! 85: { ! 86: return ino >> XFS_INO_AGINO_BITS; ! 87: } ! 88: ! 89: static inline xfs_agino_t ! 90: ino2agino (xfs_ino_t ino) ! 91: { ! 92: return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS); ! 93: } ! 94: ! 95: static inline int ! 96: ino2offset (xfs_ino_t ino) ! 97: { ! 98: return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS); ! 99: } ! 100: ! 101: static inline __uint16_t ! 102: le16 (__uint16_t x) ! 103: { ! 104: #ifdef __i386__ ! 105: __asm__("xchgb %b0,%h0" \ ! 106: : "=q" (x) \ ! 107: : "0" (x)); \ ! 108: return x; ! 109: #else ! 110: return __be16_to_cpu(x); ! 111: #endif ! 112: } ! 113: ! 114: static inline __uint32_t ! 115: le32 (__uint32_t x) ! 116: { ! 117: #ifdef __i386__ ! 118: #if 1 ! 119: /* 386 doesn't have bswap. So what. */ ! 120: __asm__("bswap %0" : "=r" (x) : "0" (x)); ! 121: #else ! 122: /* This is slower but this works on all x86 architectures. */ ! 123: __asm__("xchgb %b0, %h0" \ ! 124: "\n\troll $16, %0" \ ! 125: "\n\txchgb %b0, %h0" \ ! 126: : "=q" (x) : "0" (x)); ! 127: #endif ! 128: return x; ! 129: #else ! 130: return __be32_to_cpu(x); ! 131: #endif ! 132: } ! 133: ! 134: static inline __uint64_t ! 135: le64 (__uint64_t x) ! 136: { ! 137: __uint32_t h = x >> 32; ! 138: __uint32_t l = x & ((1ULL<<32)-1); ! 139: return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h))); ! 140: } ! 141: ! 142: ! 143: static xfs_fsblock_t ! 144: xt_start (xfs_bmbt_rec_32_t *r) ! 145: { ! 146: return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) | ! 147: (((xfs_fsblock_t)le32 (r->l2)) << 11) | ! 148: (((xfs_fsblock_t)le32 (r->l3)) >> 21); ! 149: } ! 150: ! 151: static xfs_fileoff_t ! 152: xt_offset (xfs_bmbt_rec_32_t *r) ! 153: { ! 154: return (((xfs_fileoff_t)le32 (r->l0) & ! 155: mask32lo(31)) << 23) | ! 156: (((xfs_fileoff_t)le32 (r->l1)) >> 9); ! 157: } ! 158: ! 159: static xfs_filblks_t ! 160: xt_len (xfs_bmbt_rec_32_t *r) ! 161: { ! 162: return le32(r->l3) & mask32lo(21); ! 163: } ! 164: ! 165: static inline int ! 166: xfs_highbit32(__uint32_t v) ! 167: { ! 168: int i; ! 169: ! 170: if (--v) { ! 171: for (i = 0; i < 31; i++, v >>= 1) { ! 172: if (v == 0) ! 173: return i; ! 174: } ! 175: } ! 176: return 0; ! 177: } ! 178: ! 179: static int ! 180: isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len) ! 181: { ! 182: return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; ! 183: } ! 184: ! 185: static xfs_daddr_t ! 186: agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno) ! 187: { ! 188: return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog; ! 189: } ! 190: ! 191: static xfs_daddr_t ! 192: fsb2daddr (xfs_fsblock_t fsbno) ! 193: { ! 194: return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog), ! 195: (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog))); ! 196: } ! 197: ! 198: #undef offsetof ! 199: #define offsetof(t,m) ((long)&(((t *)0)->m)) ! 200: ! 201: static inline int ! 202: btroot_maxrecs (void) ! 203: { ! 204: int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize; ! 205: ! 206: return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) / ! 207: (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)); ! 208: } ! 209: ! 210: static int ! 211: di_read (xfs_ino_t ino) ! 212: { ! 213: xfs_agino_t agino; ! 214: xfs_agnumber_t agno; ! 215: xfs_agblock_t agbno; ! 216: xfs_daddr_t daddr; ! 217: int offset; ! 218: ! 219: agno = ino2agno (ino); ! 220: agino = ino2agino (ino); ! 221: agbno = agino2agbno (agino); ! 222: offset = ino2offset (ino); ! 223: daddr = agb2daddr (agno, agbno); ! 224: ! 225: devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode); ! 226: ! 227: xfs.ptr0 = *(xfs_bmbt_ptr_t *) ! 228: (inode->di_u.di_c + sizeof(xfs_bmdr_block_t) ! 229: + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t)); ! 230: ! 231: return 1; ! 232: } ! 233: ! 234: static void ! 235: init_extents (void) ! 236: { ! 237: xfs_bmbt_ptr_t ptr0; ! 238: xfs_btree_lblock_t h; ! 239: ! 240: switch (icore.di_format) { ! 241: case XFS_DINODE_FMT_EXTENTS: ! 242: xfs.xt = inode->di_u.di_bmx; ! 243: xfs.nextents = le32 (icore.di_nextents); ! 244: break; ! 245: case XFS_DINODE_FMT_BTREE: ! 246: ptr0 = xfs.ptr0; ! 247: for (;;) { ! 248: xfs.daddr = fsb2daddr (le64(ptr0)); ! 249: devread (xfs.daddr, 0, ! 250: sizeof(xfs_btree_lblock_t), (char *)&h); ! 251: if (!h.bb_level) { ! 252: xfs.nextents = le16(h.bb_numrecs); ! 253: xfs.next = fsb2daddr (le64(h.bb_rightsib)); ! 254: xfs.fpos = sizeof(xfs_btree_block_t); ! 255: return; ! 256: } ! 257: devread (xfs.daddr, xfs.btnode_ptr0_off, ! 258: sizeof(xfs_bmbt_ptr_t), (char *)&ptr0); ! 259: } ! 260: } ! 261: } ! 262: ! 263: static xad_t * ! 264: next_extent (void) ! 265: { ! 266: static xad_t xad; ! 267: ! 268: switch (icore.di_format) { ! 269: case XFS_DINODE_FMT_EXTENTS: ! 270: if (xfs.nextents == 0) ! 271: return NULL; ! 272: break; ! 273: case XFS_DINODE_FMT_BTREE: ! 274: if (xfs.nextents == 0) { ! 275: xfs_btree_lblock_t h; ! 276: if (xfs.next == 0) ! 277: return NULL; ! 278: xfs.daddr = xfs.next; ! 279: devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h); ! 280: xfs.nextents = le16(h.bb_numrecs); ! 281: xfs.next = fsb2daddr (le64(h.bb_rightsib)); ! 282: xfs.fpos = sizeof(xfs_btree_block_t); ! 283: } ! 284: /* Yeah, I know that's slow, but I really don't care */ ! 285: devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf); ! 286: xfs.xt = (xfs_bmbt_rec_32_t *)filebuf; ! 287: xfs.fpos += sizeof(xfs_bmbt_rec_32_t); ! 288: } ! 289: xad.offset = xt_offset (xfs.xt); ! 290: xad.start = xt_start (xfs.xt); ! 291: xad.len = xt_len (xfs.xt); ! 292: ++xfs.xt; ! 293: --xfs.nextents; ! 294: ! 295: return &xad; ! 296: } ! 297: ! 298: /* ! 299: * Name lies - the function reads only first 100 bytes ! 300: */ ! 301: static void ! 302: xfs_dabread (void) ! 303: { ! 304: xad_t *xad; ! 305: xfs_fileoff_t offset;; ! 306: ! 307: init_extents (); ! 308: while ((xad = next_extent ())) { ! 309: offset = xad->offset; ! 310: if (isinxt (xfs.dablk, offset, xad->len)) { ! 311: devread (fsb2daddr (xad->start + xfs.dablk - offset), ! 312: 0, 100, dirbuf); ! 313: break; ! 314: } ! 315: } ! 316: } ! 317: ! 318: static inline xfs_ino_t ! 319: sf_ino (char *sfe, int namelen) ! 320: { ! 321: void *p = sfe + namelen + 3; ! 322: ! 323: return (xfs.i8param == 0) ! 324: ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p); ! 325: } ! 326: ! 327: static inline xfs_ino_t ! 328: sf_parent_ino (void) ! 329: { ! 330: return (xfs.i8param == 0) ! 331: ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent)) ! 332: : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent)); ! 333: } ! 334: ! 335: static inline int ! 336: roundup8 (int n) ! 337: { ! 338: return ((n+7)&~7); ! 339: } ! 340: ! 341: static char * ! 342: next_dentry (xfs_ino_t *ino) ! 343: { ! 344: int namelen = 1; ! 345: int toread; ! 346: static char *usual[2]; ! 347: static xfs_dir2_sf_entry_t *sfe; ! 348: char *name; ! 349: ! 350: if (!usual[0]) { ! 351: usual[0] = strdup("."); ! 352: usual[1] = strdup(".."); ! 353: } ! 354: name = usual[0]; ! 355: ! 356: if (xfs.dirpos >= xfs.dirmax) { ! 357: if (xfs.forw == 0) ! 358: return NULL; ! 359: xfs.dablk = xfs.forw; ! 360: xfs_dabread (); ! 361: #define h ((xfs_dir2_leaf_hdr_t *)dirbuf) ! 362: xfs.dirmax = le16 (h->count) - le16 (h->stale); ! 363: xfs.forw = le32 (h->info.forw); ! 364: #undef h ! 365: xfs.dirpos = 0; ! 366: } ! 367: ! 368: switch (icore.di_format) { ! 369: case XFS_DINODE_FMT_LOCAL: ! 370: switch (xfs.dirpos) { ! 371: case -2: ! 372: *ino = 0; ! 373: break; ! 374: case -1: ! 375: *ino = sf_parent_ino (); ! 376: ++name; ! 377: ++namelen; ! 378: sfe = (xfs_dir2_sf_entry_t *) ! 379: (inode->di_u.di_c ! 380: + sizeof(xfs_dir2_sf_hdr_t) ! 381: - xfs.i8param); ! 382: break; ! 383: default: ! 384: namelen = sfe->namelen; ! 385: *ino = sf_ino ((char *)sfe, namelen); ! 386: name = (char *)sfe->name; ! 387: sfe = (xfs_dir2_sf_entry_t *) ! 388: ((char *)sfe + namelen + 11 - xfs.i8param); ! 389: } ! 390: break; ! 391: case XFS_DINODE_FMT_BTREE: ! 392: case XFS_DINODE_FMT_EXTENTS: ! 393: #define dau ((xfs_dir2_data_union_t *)dirbuf) ! 394: for (;;) { ! 395: if (xfs.blkoff >= xfs.dirbsize) { ! 396: xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); ! 397: filepos &= ~(xfs.dirbsize - 1); ! 398: filepos |= xfs.blkoff; ! 399: } ! 400: xfs_read (dirbuf, 4); ! 401: xfs.blkoff += 4; ! 402: if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) { ! 403: toread = roundup8 (le16(dau->unused.length)) - 4; ! 404: xfs.blkoff += toread; ! 405: filepos += toread; ! 406: continue; ! 407: } ! 408: break; ! 409: } ! 410: xfs_read ((char *)dirbuf + 4, 5); ! 411: *ino = le64 (dau->entry.inumber); ! 412: namelen = dau->entry.namelen; ! 413: #undef dau ! 414: toread = roundup8 (namelen + 11) - 9; ! 415: xfs_read (dirbuf, toread); ! 416: name = (char *)dirbuf; ! 417: xfs.blkoff += toread + 5; ! 418: } ! 419: ++xfs.dirpos; ! 420: name[namelen] = 0; ! 421: ! 422: return name; ! 423: } ! 424: ! 425: static char * ! 426: first_dentry (xfs_ino_t *ino) ! 427: { ! 428: xfs.forw = 0; ! 429: switch (icore.di_format) { ! 430: case XFS_DINODE_FMT_LOCAL: ! 431: xfs.dirmax = inode->di_u.di_dir2sf.hdr.count; ! 432: xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4; ! 433: xfs.dirpos = -2; ! 434: break; ! 435: case XFS_DINODE_FMT_EXTENTS: ! 436: case XFS_DINODE_FMT_BTREE: ! 437: filepos = 0; ! 438: xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t)); ! 439: if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) { ! 440: #define tail ((xfs_dir2_block_tail_t *)dirbuf) ! 441: filepos = xfs.dirbsize - sizeof(*tail); ! 442: xfs_read (dirbuf, sizeof(*tail)); ! 443: xfs.dirmax = le32 (tail->count) - le32 (tail->stale); ! 444: #undef tail ! 445: } else { ! 446: xfs.dablk = (1ULL << 35) >> xfs.blklog; ! 447: #define h ((xfs_dir2_leaf_hdr_t *)dirbuf) ! 448: #define n ((xfs_da_intnode_t *)dirbuf) ! 449: for (;;) { ! 450: xfs_dabread (); ! 451: if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC)) ! 452: || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) { ! 453: xfs.dirmax = le16 (h->count) - le16 (h->stale); ! 454: xfs.forw = le32 (h->info.forw); ! 455: break; ! 456: } ! 457: xfs.dablk = le32 (n->btree[0].before); ! 458: } ! 459: #undef n ! 460: #undef h ! 461: } ! 462: xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); ! 463: filepos = xfs.blkoff; ! 464: xfs.dirpos = 0; ! 465: } ! 466: return next_dentry (ino); ! 467: } ! 468: ! 469: int ! 470: xfs_mount (void) ! 471: { ! 472: xfs_sb_t super; ! 473: ! 474: if (!devread (0, 0, sizeof(super), (char *)&super) ! 475: || (le32(super.sb_magicnum) != XFS_SB_MAGIC) ! 476: || ((le16(super.sb_versionnum) ! 477: & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) { ! 478: return 0; ! 479: } ! 480: ! 481: xfs.bsize = le32 (super.sb_blocksize); ! 482: xfs.blklog = super.sb_blocklog; ! 483: xfs.bdlog = xfs.blklog - SECTOR_BITS; ! 484: xfs.rootino = le64 (super.sb_rootino); ! 485: xfs.isize = le16 (super.sb_inodesize); ! 486: xfs.agblocks = le32 (super.sb_agblocks); ! 487: xfs.dirbsize = xfs.bsize << super.sb_dirblklog; ! 488: ! 489: xfs.inopblog = super.sb_inopblog; ! 490: xfs.agblklog = super.sb_agblklog; ! 491: xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount)); ! 492: ! 493: xfs.btnode_ptr0_off = ! 494: ((xfs.bsize - sizeof(xfs_btree_block_t)) / ! 495: (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t))) ! 496: * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t); ! 497: ! 498: return 1; ! 499: } ! 500: ! 501: int ! 502: xfs_read (char *buf, int len) ! 503: { ! 504: xad_t *xad; ! 505: xfs_fileoff_t endofprev, endofcur, offset; ! 506: xfs_filblks_t xadlen; ! 507: int toread, startpos, endpos; ! 508: ! 509: if (icore.di_format == XFS_DINODE_FMT_LOCAL) { ! 510: grub_memmove (buf, inode->di_u.di_c + filepos, len); ! 511: filepos += len; ! 512: return len; ! 513: } ! 514: ! 515: startpos = filepos; ! 516: endpos = filepos + len; ! 517: endofprev = (xfs_fileoff_t)-1; ! 518: init_extents (); ! 519: while (len > 0 && (xad = next_extent ())) { ! 520: offset = xad->offset; ! 521: xadlen = xad->len; ! 522: if (isinxt (filepos >> xfs.blklog, offset, xadlen)) { ! 523: endofcur = (offset + xadlen) << xfs.blklog; ! 524: toread = (endofcur >= endpos) ! 525: ? len : (endofcur - filepos); ! 526: ! 527: disk_read_func = disk_read_hook; ! 528: devread (fsb2daddr (xad->start), ! 529: filepos - (offset << xfs.blklog), toread, buf); ! 530: disk_read_func = NULL; ! 531: ! 532: buf += toread; ! 533: len -= toread; ! 534: filepos += toread; ! 535: } else if (offset > endofprev) { ! 536: toread = ((offset << xfs.blklog) >= endpos) ! 537: ? len : ((offset - endofprev) << xfs.blklog); ! 538: len -= toread; ! 539: filepos += toread; ! 540: for (; toread; toread--) { ! 541: *buf++ = 0; ! 542: } ! 543: continue; ! 544: } ! 545: endofprev = offset + xadlen; ! 546: } ! 547: ! 548: return filepos - startpos; ! 549: } ! 550: ! 551: int ! 552: xfs_dir (char *dirname) ! 553: { ! 554: xfs_ino_t ino, parent_ino, new_ino; ! 555: xfs_fsize_t di_size; ! 556: int di_mode; ! 557: int cmp, n, link_count; ! 558: char linkbuf[xfs.bsize]; ! 559: char *rest, *name, ch; ! 560: ! 561: parent_ino = ino = xfs.rootino; ! 562: link_count = 0; ! 563: for (;;) { ! 564: di_read (ino); ! 565: di_size = le64 (icore.di_size); ! 566: di_mode = le16 (icore.di_mode); ! 567: ! 568: if ((di_mode & IFMT) == IFLNK) { ! 569: if (++link_count > MAX_LINK_COUNT) { ! 570: errnum = ERR_SYMLINK_LOOP; ! 571: return 0; ! 572: } ! 573: if (di_size < xfs.bsize - 1) { ! 574: filepos = 0; ! 575: filemax = di_size; ! 576: n = xfs_read (linkbuf, filemax); ! 577: } else { ! 578: errnum = ERR_FILELENGTH; ! 579: return 0; ! 580: } ! 581: ! 582: ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino; ! 583: while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++)); ! 584: linkbuf[n] = 0; ! 585: dirname = linkbuf; ! 586: continue; ! 587: } ! 588: ! 589: if (!*dirname || isspace (*dirname)) { ! 590: if ((di_mode & IFMT) != IFREG) { ! 591: errnum = ERR_BAD_FILETYPE; ! 592: return 0; ! 593: } ! 594: filepos = 0; ! 595: filemax = di_size; ! 596: return 1; ! 597: } ! 598: ! 599: if ((di_mode & IFMT) != IFDIR) { ! 600: errnum = ERR_BAD_FILETYPE; ! 601: return 0; ! 602: } ! 603: ! 604: for (; *dirname == '/'; dirname++); ! 605: ! 606: for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); ! 607: *rest = 0; ! 608: ! 609: name = first_dentry (&new_ino); ! 610: for (;;) { ! 611: cmp = (!*dirname) ? -1 : substring (dirname, name); ! 612: #ifndef STAGE1_5 ! 613: if (print_possibilities && ch != '/' && cmp <= 0) { ! 614: if (print_possibilities > 0) ! 615: print_possibilities = -print_possibilities; ! 616: print_a_completion (name); ! 617: } else ! 618: #endif ! 619: if (cmp == 0) { ! 620: parent_ino = ino; ! 621: if (new_ino) ! 622: ino = new_ino; ! 623: *(dirname = rest) = ch; ! 624: break; ! 625: } ! 626: name = next_dentry (&new_ino); ! 627: if (name == NULL) { ! 628: if (print_possibilities < 0) ! 629: return 1; ! 630: ! 631: errnum = ERR_FILE_NOT_FOUND; ! 632: *rest = ch; ! 633: return 0; ! 634: } ! 635: } ! 636: } ! 637: } ! 638: ! 639: #endif /* FSYS_XFS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.