1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 4 * All Rights Reserved. 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_log_format.h" 11 #include "xfs_trans_resv.h" 12 #include "xfs_mount.h" 13 #include "xfs_inode.h" 14 #include "xfs_trans.h" 15 #include "xfs_bmap.h" 16 #include "xfs_dir2.h" 17 #include "xfs_dir2_priv.h" 18 #include "xfs_errortag.h" 19 #include "xfs_error.h" 20 #include "xfs_trace.h" 21 22 struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; 23 24 /* 25 * Convert inode mode to directory entry filetype 26 */ 27 unsigned char 28 xfs_mode_to_ftype( 29 int mode) 30 { 31 switch (mode & S_IFMT) { 32 case S_IFREG: 33 return XFS_DIR3_FT_REG_FILE; 34 case S_IFDIR: 35 return XFS_DIR3_FT_DIR; 36 case S_IFCHR: 37 return XFS_DIR3_FT_CHRDEV; 38 case S_IFBLK: 39 return XFS_DIR3_FT_BLKDEV; 40 case S_IFIFO: 41 return XFS_DIR3_FT_FIFO; 42 case S_IFSOCK: 43 return XFS_DIR3_FT_SOCK; 44 case S_IFLNK: 45 return XFS_DIR3_FT_SYMLINK; 46 default: 47 return XFS_DIR3_FT_UNKNOWN; 48 } 49 } 50 51 /* 52 * ASCII case-insensitive (ie. A-Z) support for directories that was 53 * used in IRIX. 54 */ 55 xfs_dahash_t 56 xfs_ascii_ci_hashname( 57 struct xfs_name *name) 58 { 59 xfs_dahash_t hash; 60 int i; 61 62 for (i = 0, hash = 0; i < name->len; i++) 63 hash = tolower(name->name[i]) ^ rol32(hash, 7); 64 65 return hash; 66 } 67 68 enum xfs_dacmp 69 xfs_ascii_ci_compname( 70 struct xfs_da_args *args, 71 const unsigned char *name, 72 int len) 73 { 74 enum xfs_dacmp result; 75 int i; 76 77 if (args->namelen != len) 78 return XFS_CMP_DIFFERENT; 79 80 result = XFS_CMP_EXACT; 81 for (i = 0; i < len; i++) { 82 if (args->name[i] == name[i]) 83 continue; 84 if (tolower(args->name[i]) != tolower(name[i])) 85 return XFS_CMP_DIFFERENT; 86 result = XFS_CMP_CASE; 87 } 88 89 return result; 90 } 91 92 int 93 xfs_da_mount( 94 struct xfs_mount *mp) 95 { 96 struct xfs_da_geometry *dageo; 97 98 99 ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT); 100 ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE); 101 102 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), 103 KM_MAYFAIL); 104 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry), 105 KM_MAYFAIL); 106 if (!mp->m_dir_geo || !mp->m_attr_geo) { 107 kmem_free(mp->m_dir_geo); 108 kmem_free(mp->m_attr_geo); 109 return -ENOMEM; 110 } 111 112 /* set up directory geometry */ 113 dageo = mp->m_dir_geo; 114 dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog; 115 dageo->fsblog = mp->m_sb.sb_blocklog; 116 dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb); 117 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog; 118 if (xfs_sb_version_hascrc(&mp->m_sb)) { 119 dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr); 120 dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr); 121 dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr); 122 dageo->data_entry_offset = 123 sizeof(struct xfs_dir3_data_hdr); 124 } else { 125 dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr); 126 dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr); 127 dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr); 128 dageo->data_entry_offset = 129 sizeof(struct xfs_dir2_data_hdr); 130 } 131 dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) / 132 sizeof(struct xfs_dir2_leaf_entry); 133 dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) / 134 sizeof(xfs_dir2_data_off_t); 135 136 dageo->data_first_offset = dageo->data_entry_offset + 137 xfs_dir2_data_entsize(mp, 1) + 138 xfs_dir2_data_entsize(mp, 2); 139 140 /* 141 * Now we've set up the block conversion variables, we can calculate the 142 * segment block constants using the geometry structure. 143 */ 144 dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET); 145 dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET); 146 dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET); 147 dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) / 148 (uint)sizeof(xfs_da_node_entry_t); 149 dageo->magicpct = (dageo->blksize * 37) / 100; 150 151 /* set up attribute geometry - single fsb only */ 152 dageo = mp->m_attr_geo; 153 dageo->blklog = mp->m_sb.sb_blocklog; 154 dageo->fsblog = mp->m_sb.sb_blocklog; 155 dageo->blksize = 1 << dageo->blklog; 156 dageo->fsbcount = 1; 157 dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size; 158 dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) / 159 (uint)sizeof(xfs_da_node_entry_t); 160 dageo->magicpct = (dageo->blksize * 37) / 100; 161 return 0; 162 } 163 164 void 165 xfs_da_unmount( 166 struct xfs_mount *mp) 167 { 168 kmem_free(mp->m_dir_geo); 169 kmem_free(mp->m_attr_geo); 170 } 171 172 /* 173 * Return 1 if directory contains only "." and "..". 174 */ 175 int 176 xfs_dir_isempty( 177 xfs_inode_t *dp) 178 { 179 xfs_dir2_sf_hdr_t *sfp; 180 181 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 182 if (dp->i_d.di_size == 0) /* might happen during shutdown. */ 183 return 1; 184 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 185 return 0; 186 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 187 return !sfp->count; 188 } 189 190 /* 191 * Validate a given inode number. 192 */ 193 int 194 xfs_dir_ino_validate( 195 xfs_mount_t *mp, 196 xfs_ino_t ino) 197 { 198 bool ino_ok = xfs_verify_dir_ino(mp, ino); 199 200 if (XFS_IS_CORRUPT(mp, !ino_ok) || 201 XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) { 202 xfs_warn(mp, "Invalid inode number 0x%Lx", 203 (unsigned long long) ino); 204 return -EFSCORRUPTED; 205 } 206 return 0; 207 } 208 209 /* 210 * Initialize a directory with its "." and ".." entries. 211 */ 212 int 213 xfs_dir_init( 214 xfs_trans_t *tp, 215 xfs_inode_t *dp, 216 xfs_inode_t *pdp) 217 { 218 struct xfs_da_args *args; 219 int error; 220 221 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 222 error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); 223 if (error) 224 return error; 225 226 args = kmem_zalloc(sizeof(*args), KM_NOFS); 227 if (!args) 228 return -ENOMEM; 229 230 args->geo = dp->i_mount->m_dir_geo; 231 args->dp = dp; 232 args->trans = tp; 233 error = xfs_dir2_sf_create(args, pdp->i_ino); 234 kmem_free(args); 235 return error; 236 } 237 238 /* 239 * Enter a name in a directory, or check for available space. 240 * If inum is 0, only the available space test is performed. 241 */ 242 int 243 xfs_dir_createname( 244 struct xfs_trans *tp, 245 struct xfs_inode *dp, 246 struct xfs_name *name, 247 xfs_ino_t inum, /* new entry inode number */ 248 xfs_extlen_t total) /* bmap's total block count */ 249 { 250 struct xfs_da_args *args; 251 int rval; 252 int v; /* type-checking value */ 253 254 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 255 256 if (inum) { 257 rval = xfs_dir_ino_validate(tp->t_mountp, inum); 258 if (rval) 259 return rval; 260 XFS_STATS_INC(dp->i_mount, xs_dir_create); 261 } 262 263 args = kmem_zalloc(sizeof(*args), KM_NOFS); 264 if (!args) 265 return -ENOMEM; 266 267 args->geo = dp->i_mount->m_dir_geo; 268 args->name = name->name; 269 args->namelen = name->len; 270 args->filetype = name->type; 271 args->hashval = xfs_dir2_hashname(dp->i_mount, name); 272 args->inumber = inum; 273 args->dp = dp; 274 args->total = total; 275 args->whichfork = XFS_DATA_FORK; 276 args->trans = tp; 277 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; 278 if (!inum) 279 args->op_flags |= XFS_DA_OP_JUSTCHECK; 280 281 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 282 rval = xfs_dir2_sf_addname(args); 283 goto out_free; 284 } 285 286 rval = xfs_dir2_isblock(args, &v); 287 if (rval) 288 goto out_free; 289 if (v) { 290 rval = xfs_dir2_block_addname(args); 291 goto out_free; 292 } 293 294 rval = xfs_dir2_isleaf(args, &v); 295 if (rval) 296 goto out_free; 297 if (v) 298 rval = xfs_dir2_leaf_addname(args); 299 else 300 rval = xfs_dir2_node_addname(args); 301 302 out_free: 303 kmem_free(args); 304 return rval; 305 } 306 307 /* 308 * If doing a CI lookup and case-insensitive match, dup actual name into 309 * args.value. Return EEXIST for success (ie. name found) or an error. 310 */ 311 int 312 xfs_dir_cilookup_result( 313 struct xfs_da_args *args, 314 const unsigned char *name, 315 int len) 316 { 317 if (args->cmpresult == XFS_CMP_DIFFERENT) 318 return -ENOENT; 319 if (args->cmpresult != XFS_CMP_CASE || 320 !(args->op_flags & XFS_DA_OP_CILOOKUP)) 321 return -EEXIST; 322 323 args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL); 324 if (!args->value) 325 return -ENOMEM; 326 327 memcpy(args->value, name, len); 328 args->valuelen = len; 329 return -EEXIST; 330 } 331 332 /* 333 * Lookup a name in a directory, give back the inode number. 334 * If ci_name is not NULL, returns the actual name in ci_name if it differs 335 * to name, or ci_name->name is set to NULL for an exact match. 336 */ 337 338 int 339 xfs_dir_lookup( 340 xfs_trans_t *tp, 341 xfs_inode_t *dp, 342 struct xfs_name *name, 343 xfs_ino_t *inum, /* out: inode number */ 344 struct xfs_name *ci_name) /* out: actual name if CI match */ 345 { 346 struct xfs_da_args *args; 347 int rval; 348 int v; /* type-checking value */ 349 int lock_mode; 350 351 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 352 XFS_STATS_INC(dp->i_mount, xs_dir_lookup); 353 354 /* 355 * We need to use KM_NOFS here so that lockdep will not throw false 356 * positive deadlock warnings on a non-transactional lookup path. It is 357 * safe to recurse into inode recalim in that case, but lockdep can't 358 * easily be taught about it. Hence KM_NOFS avoids having to add more 359 * lockdep Doing this avoids having to add a bunch of lockdep class 360 * annotations into the reclaim path for the ilock. 361 */ 362 args = kmem_zalloc(sizeof(*args), KM_NOFS); 363 args->geo = dp->i_mount->m_dir_geo; 364 args->name = name->name; 365 args->namelen = name->len; 366 args->filetype = name->type; 367 args->hashval = xfs_dir2_hashname(dp->i_mount, name); 368 args->dp = dp; 369 args->whichfork = XFS_DATA_FORK; 370 args->trans = tp; 371 args->op_flags = XFS_DA_OP_OKNOENT; 372 if (ci_name) 373 args->op_flags |= XFS_DA_OP_CILOOKUP; 374 375 lock_mode = xfs_ilock_data_map_shared(dp); 376 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 377 rval = xfs_dir2_sf_lookup(args); 378 goto out_check_rval; 379 } 380 381 rval = xfs_dir2_isblock(args, &v); 382 if (rval) 383 goto out_free; 384 if (v) { 385 rval = xfs_dir2_block_lookup(args); 386 goto out_check_rval; 387 } 388 389 rval = xfs_dir2_isleaf(args, &v); 390 if (rval) 391 goto out_free; 392 if (v) 393 rval = xfs_dir2_leaf_lookup(args); 394 else 395 rval = xfs_dir2_node_lookup(args); 396 397 out_check_rval: 398 if (rval == -EEXIST) 399 rval = 0; 400 if (!rval) { 401 *inum = args->inumber; 402 if (ci_name) { 403 ci_name->name = args->value; 404 ci_name->len = args->valuelen; 405 } 406 } 407 out_free: 408 xfs_iunlock(dp, lock_mode); 409 kmem_free(args); 410 return rval; 411 } 412 413 /* 414 * Remove an entry from a directory. 415 */ 416 int 417 xfs_dir_removename( 418 struct xfs_trans *tp, 419 struct xfs_inode *dp, 420 struct xfs_name *name, 421 xfs_ino_t ino, 422 xfs_extlen_t total) /* bmap's total block count */ 423 { 424 struct xfs_da_args *args; 425 int rval; 426 int v; /* type-checking value */ 427 428 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 429 XFS_STATS_INC(dp->i_mount, xs_dir_remove); 430 431 args = kmem_zalloc(sizeof(*args), KM_NOFS); 432 if (!args) 433 return -ENOMEM; 434 435 args->geo = dp->i_mount->m_dir_geo; 436 args->name = name->name; 437 args->namelen = name->len; 438 args->filetype = name->type; 439 args->hashval = xfs_dir2_hashname(dp->i_mount, name); 440 args->inumber = ino; 441 args->dp = dp; 442 args->total = total; 443 args->whichfork = XFS_DATA_FORK; 444 args->trans = tp; 445 446 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 447 rval = xfs_dir2_sf_removename(args); 448 goto out_free; 449 } 450 451 rval = xfs_dir2_isblock(args, &v); 452 if (rval) 453 goto out_free; 454 if (v) { 455 rval = xfs_dir2_block_removename(args); 456 goto out_free; 457 } 458 459 rval = xfs_dir2_isleaf(args, &v); 460 if (rval) 461 goto out_free; 462 if (v) 463 rval = xfs_dir2_leaf_removename(args); 464 else 465 rval = xfs_dir2_node_removename(args); 466 out_free: 467 kmem_free(args); 468 return rval; 469 } 470 471 /* 472 * Replace the inode number of a directory entry. 473 */ 474 int 475 xfs_dir_replace( 476 struct xfs_trans *tp, 477 struct xfs_inode *dp, 478 struct xfs_name *name, /* name of entry to replace */ 479 xfs_ino_t inum, /* new inode number */ 480 xfs_extlen_t total) /* bmap's total block count */ 481 { 482 struct xfs_da_args *args; 483 int rval; 484 int v; /* type-checking value */ 485 486 ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 487 488 rval = xfs_dir_ino_validate(tp->t_mountp, inum); 489 if (rval) 490 return rval; 491 492 args = kmem_zalloc(sizeof(*args), KM_NOFS); 493 if (!args) 494 return -ENOMEM; 495 496 args->geo = dp->i_mount->m_dir_geo; 497 args->name = name->name; 498 args->namelen = name->len; 499 args->filetype = name->type; 500 args->hashval = xfs_dir2_hashname(dp->i_mount, name); 501 args->inumber = inum; 502 args->dp = dp; 503 args->total = total; 504 args->whichfork = XFS_DATA_FORK; 505 args->trans = tp; 506 507 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 508 rval = xfs_dir2_sf_replace(args); 509 goto out_free; 510 } 511 512 rval = xfs_dir2_isblock(args, &v); 513 if (rval) 514 goto out_free; 515 if (v) { 516 rval = xfs_dir2_block_replace(args); 517 goto out_free; 518 } 519 520 rval = xfs_dir2_isleaf(args, &v); 521 if (rval) 522 goto out_free; 523 if (v) 524 rval = xfs_dir2_leaf_replace(args); 525 else 526 rval = xfs_dir2_node_replace(args); 527 out_free: 528 kmem_free(args); 529 return rval; 530 } 531 532 /* 533 * See if this entry can be added to the directory without allocating space. 534 */ 535 int 536 xfs_dir_canenter( 537 xfs_trans_t *tp, 538 xfs_inode_t *dp, 539 struct xfs_name *name) /* name of entry to add */ 540 { 541 return xfs_dir_createname(tp, dp, name, 0, 0); 542 } 543 544 /* 545 * Utility routines. 546 */ 547 548 /* 549 * Add a block to the directory. 550 * 551 * This routine is for data and free blocks, not leaf/node blocks which are 552 * handled by xfs_da_grow_inode. 553 */ 554 int 555 xfs_dir2_grow_inode( 556 struct xfs_da_args *args, 557 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 558 xfs_dir2_db_t *dbp) /* out: block number added */ 559 { 560 struct xfs_inode *dp = args->dp; 561 struct xfs_mount *mp = dp->i_mount; 562 xfs_fileoff_t bno; /* directory offset of new block */ 563 int count; /* count of filesystem blocks */ 564 int error; 565 566 trace_xfs_dir2_grow_inode(args, space); 567 568 /* 569 * Set lowest possible block in the space requested. 570 */ 571 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); 572 count = args->geo->fsbcount; 573 574 error = xfs_da_grow_inode_int(args, &bno, count); 575 if (error) 576 return error; 577 578 *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno); 579 580 /* 581 * Update file's size if this is the data space and it grew. 582 */ 583 if (space == XFS_DIR2_DATA_SPACE) { 584 xfs_fsize_t size; /* directory file (data) size */ 585 586 size = XFS_FSB_TO_B(mp, bno + count); 587 if (size > dp->i_d.di_size) { 588 dp->i_d.di_size = size; 589 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 590 } 591 } 592 return 0; 593 } 594 595 /* 596 * See if the directory is a single-block form directory. 597 */ 598 int 599 xfs_dir2_isblock( 600 struct xfs_da_args *args, 601 int *vp) /* out: 1 is block, 0 is not block */ 602 { 603 xfs_fileoff_t last; /* last file offset */ 604 int rval; 605 606 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) 607 return rval; 608 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; 609 if (XFS_IS_CORRUPT(args->dp->i_mount, 610 rval != 0 && 611 args->dp->i_d.di_size != args->geo->blksize)) 612 return -EFSCORRUPTED; 613 *vp = rval; 614 return 0; 615 } 616 617 /* 618 * See if the directory is a single-leaf form directory. 619 */ 620 int 621 xfs_dir2_isleaf( 622 struct xfs_da_args *args, 623 int *vp) /* out: 1 is block, 0 is not block */ 624 { 625 xfs_fileoff_t last; /* last file offset */ 626 int rval; 627 628 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) 629 return rval; 630 *vp = last == args->geo->leafblk + args->geo->fsbcount; 631 return 0; 632 } 633 634 /* 635 * Remove the given block from the directory. 636 * This routine is used for data and free blocks, leaf/node are done 637 * by xfs_da_shrink_inode. 638 */ 639 int 640 xfs_dir2_shrink_inode( 641 struct xfs_da_args *args, 642 xfs_dir2_db_t db, 643 struct xfs_buf *bp) 644 { 645 xfs_fileoff_t bno; /* directory file offset */ 646 xfs_dablk_t da; /* directory file offset */ 647 int done; /* bunmap is finished */ 648 struct xfs_inode *dp; 649 int error; 650 struct xfs_mount *mp; 651 struct xfs_trans *tp; 652 653 trace_xfs_dir2_shrink_inode(args, db); 654 655 dp = args->dp; 656 mp = dp->i_mount; 657 tp = args->trans; 658 da = xfs_dir2_db_to_da(args->geo, db); 659 660 /* Unmap the fsblock(s). */ 661 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done); 662 if (error) { 663 /* 664 * ENOSPC actually can happen if we're in a removename with no 665 * space reservation, and the resulting block removal would 666 * cause a bmap btree split or conversion from extents to btree. 667 * This can only happen for un-fragmented directory blocks, 668 * since you need to be punching out the middle of an extent. 669 * In this case we need to leave the block in the file, and not 670 * binval it. So the block has to be in a consistent empty 671 * state and appropriately logged. We don't free up the buffer, 672 * the caller can tell it hasn't happened since it got an error 673 * back. 674 */ 675 return error; 676 } 677 ASSERT(done); 678 /* 679 * Invalidate the buffer from the transaction. 680 */ 681 xfs_trans_binval(tp, bp); 682 /* 683 * If it's not a data block, we're done. 684 */ 685 if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)) 686 return 0; 687 /* 688 * If the block isn't the last one in the directory, we're done. 689 */ 690 if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0)) 691 return 0; 692 bno = da; 693 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { 694 /* 695 * This can't really happen unless there's kernel corruption. 696 */ 697 return error; 698 } 699 if (db == args->geo->datablk) 700 ASSERT(bno == 0); 701 else 702 ASSERT(bno > 0); 703 /* 704 * Set the size to the new last block. 705 */ 706 dp->i_d.di_size = XFS_FSB_TO_B(mp, bno); 707 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 708 return 0; 709 } 710 711 /* Returns true if the directory entry name is valid. */ 712 bool 713 xfs_dir2_namecheck( 714 const void *name, 715 size_t length) 716 { 717 /* 718 * MAXNAMELEN includes the trailing null, but (name/length) leave it 719 * out, so use >= for the length check. 720 */ 721 if (length >= MAXNAMELEN) 722 return false; 723 724 /* There shouldn't be any slashes or nulls here */ 725 return !memchr(name, '/', length) && !memchr(name, 0, length); 726 } 727