root/maint/gnulib/tests/test-rename.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. dentry_exists
  2. assert_nonexistent
  3. test_rename

   1 /* Test of rename() function.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* This file is designed to test both rename(a,b) and
  18    renameat(AT_FDCWD,a,AT_FDCWD,b).  FUNC is the function to test.
  19    Assumes that BASE and ASSERT are already defined, and that
  20    appropriate headers are already included.  If PRINT, warn before
  21    skipping symlink tests with status 77.  */
  22 
  23 /* Tests whether a file, given by a file name without slashes, exists in
  24    the current directory, by scanning the directory entries.  */
  25 static bool
  26 dentry_exists (const char *filename)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28   bool exists = false;
  29   DIR *dir = opendir (".");
  30 
  31   ASSERT (dir != NULL);
  32   for (;;)
  33     {
  34       struct dirent *d = readdir (dir);
  35       if (d == NULL)
  36         break;
  37       if (strcmp (d->d_name, filename) == 0)
  38         {
  39           exists = true;
  40           break;
  41         }
  42     }
  43   ASSERT (closedir (dir) == 0);
  44   return exists;
  45 }
  46 
  47 /* Asserts that a specific file, given by a file name without slashes, does
  48    not exist in the current directory.  */
  49 static void
  50 assert_nonexistent (const char *filename)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52   struct stat st;
  53 
  54   /* The usual way to test the presence of a file is via stat() or lstat().  */
  55   errno = 0;
  56   if (stat (filename, &st) == -1)
  57     ASSERT (errno == ENOENT);
  58   else
  59     {
  60       /* But after renaming a directory over an empty directory on an NFS-
  61          mounted file system, on Linux 2.6.18, for a period of 30 seconds the
  62          old directory name is "present" according to stat() but "nonexistent"
  63          according to dentry_exists().  */
  64       ASSERT (!dentry_exists (filename));
  65       /* Remove the old directory name, so that subsequent mkdir calls
  66          succeed.  */
  67       (void) rmdir (filename);
  68     }
  69 }
  70 
  71 static int
  72 test_rename (int (*func) (char const *, char const *), bool print)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74   /* Setup.  */
  75   struct stat st;
  76   int fd = creat (BASE "file", 0600);
  77   ASSERT (0 <= fd);
  78   ASSERT (write (fd, "hi", 2) == 2);
  79   ASSERT (close (fd) == 0);
  80   ASSERT (mkdir (BASE "dir", 0700) == 0);
  81 
  82   /* Files present here:
  83        {BASE}file
  84        {BASE}dir/
  85    */
  86 
  87   /* Obvious errors.  */
  88 
  89   { /* Missing source.  */
  90     {
  91       errno = 0;
  92       ASSERT (func (BASE "missing", BASE "missing") == -1);
  93       ASSERT (errno == ENOENT);
  94     }
  95     {
  96       errno = 0;
  97       ASSERT (func (BASE "missing/", BASE "missing") == -1);
  98       ASSERT (errno == ENOENT);
  99     }
 100     {
 101       errno = 0;
 102       ASSERT (func (BASE "missing", BASE "missing/") == -1);
 103       ASSERT (errno == ENOENT);
 104     }
 105   }
 106   { /* Empty operand.  */
 107     {
 108       errno = 0;
 109       ASSERT (func ("", BASE "missing") == -1);
 110       ASSERT (errno == ENOENT);
 111     }
 112     {
 113       errno = 0;
 114       ASSERT (func (BASE "file", "") == -1);
 115       ASSERT (errno == ENOENT);
 116     }
 117     {
 118       errno = 0;
 119       ASSERT (func (BASE "", "") == -1);
 120       ASSERT (errno == ENOENT);
 121     }
 122   }
 123 
 124   /* Files.  */
 125 
 126   { /* Trailing slash.  */
 127     {
 128       errno = 0;
 129       ASSERT (func (BASE "file", BASE "file2/") == -1);
 130       ASSERT (errno == ENOENT || errno == ENOTDIR);
 131     }
 132     {
 133       errno = 0;
 134       ASSERT (func (BASE "file/", BASE "file2") == -1);
 135       ASSERT (errno == ENOTDIR);
 136     }
 137     {
 138       errno = 0;
 139       ASSERT (stat (BASE "file2", &st) == -1);
 140       ASSERT (errno == ENOENT);
 141     }
 142   }
 143   { /* Simple rename.  */
 144     ASSERT (func (BASE "file", BASE "file2") == 0);
 145     errno = 0;
 146     ASSERT (stat (BASE "file", &st) == -1);
 147     ASSERT (errno == ENOENT);
 148     memset (&st, 0, sizeof st);
 149     ASSERT (stat (BASE "file2", &st) == 0);
 150     ASSERT (st.st_size == 2);
 151   }
 152   /* Files present here:
 153        {BASE}file2
 154        {BASE}dir/
 155    */
 156   { /* Overwrite.  */
 157     ASSERT (close (creat (BASE "file", 0600)) == 0);
 158     errno = 0;
 159     ASSERT (func (BASE "file2", BASE "file/") == -1);
 160     ASSERT (errno == ENOTDIR);
 161     ASSERT (func (BASE "file2", BASE "file") == 0);
 162     memset (&st, 0, sizeof st);
 163     ASSERT (stat (BASE "file", &st) == 0);
 164     ASSERT (st.st_size == 2);
 165     errno = 0;
 166     ASSERT (stat (BASE "file2", &st) == -1);
 167     ASSERT (errno == ENOENT);
 168   }
 169   /* Files present here:
 170        {BASE}file
 171        {BASE}dir/
 172    */
 173 
 174   /* Directories.  */
 175 
 176   { /* Simple rename.  */
 177     {
 178       ASSERT (func (BASE "dir", BASE "dir2/") == 0);
 179       errno = 0;
 180       ASSERT (stat (BASE "dir", &st) == -1);
 181       ASSERT (errno == ENOENT);
 182       ASSERT (stat (BASE "dir2", &st) == 0);
 183     }
 184     /* Files present here:
 185          {BASE}file
 186          {BASE}dir2/
 187      */
 188     {
 189       ASSERT (func (BASE "dir2/", BASE "dir") == 0);
 190       ASSERT (stat (BASE "dir", &st) == 0);
 191       errno = 0;
 192       ASSERT (stat (BASE "dir2", &st) == -1);
 193       ASSERT (errno == ENOENT);
 194     }
 195     /* Files present here:
 196          {BASE}file
 197          {BASE}dir/
 198      */
 199     {
 200       ASSERT (func (BASE "dir", BASE "dir2") == 0);
 201       errno = 0;
 202       ASSERT (stat (BASE "dir", &st) == -1);
 203       ASSERT (errno == ENOENT);
 204       ASSERT (stat (BASE "dir2", &st) == 0);
 205     }
 206     /* Files present here:
 207          {BASE}file
 208          {BASE}dir2/
 209      */
 210     { /* Empty onto empty.  */
 211       ASSERT (mkdir (BASE "dir", 0700) == 0);
 212       /* Files present here:
 213            {BASE}file
 214            {BASE}dir/
 215            {BASE}dir2/
 216        */
 217       ASSERT (func (BASE "dir2", BASE "dir") == 0);
 218       /* Files present here:
 219            {BASE}file
 220            {BASE}dir/
 221        */
 222       ASSERT (mkdir (BASE "dir2", 0700) == 0);
 223       /* Files present here:
 224            {BASE}file
 225            {BASE}dir/
 226            {BASE}dir2/
 227        */
 228       ASSERT (func (BASE "dir2", BASE "dir/") == 0);
 229       /* Files present here:
 230            {BASE}file
 231            {BASE}dir/
 232        */
 233       ASSERT (mkdir (BASE "dir2", 0700) == 0);
 234       /* Files present here:
 235            {BASE}file
 236            {BASE}dir/
 237            {BASE}dir2/
 238        */
 239       ASSERT (func (BASE "dir2/", BASE "dir") == 0);
 240       /* Files present here:
 241            {BASE}file
 242            {BASE}dir/
 243        */
 244       ASSERT (mkdir (BASE "dir2", 0700) == 0);
 245     }
 246     /* Files present here:
 247          {BASE}file
 248          {BASE}dir/
 249          {BASE}dir2/
 250      */
 251     { /* Empty onto full.  */
 252       ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
 253       /* Files present here:
 254            {BASE}file
 255            {BASE}dir/
 256            {BASE}dir/file
 257            {BASE}dir2/
 258        */
 259       {
 260         errno = 0;
 261         ASSERT (func (BASE "dir2", BASE "dir") == -1);
 262         ASSERT (errno == EEXIST || errno == ENOTEMPTY);
 263       }
 264       {
 265         errno = 0;
 266         ASSERT (func (BASE "dir2/", BASE "dir") == -1);
 267         ASSERT (errno == EEXIST || errno == ENOTEMPTY);
 268       }
 269       {
 270         errno = 0;
 271         ASSERT (func (BASE "dir2", BASE "dir/") == -1);
 272         ASSERT (errno == EEXIST || errno == ENOTEMPTY);
 273       }
 274     }
 275     { /* Full onto empty.  */
 276       ASSERT (func (BASE "dir", BASE "dir2") == 0);
 277       assert_nonexistent (BASE "dir");
 278       ASSERT (stat (BASE "dir2/file", &st) == 0);
 279       /* Files present here:
 280            {BASE}file
 281            {BASE}dir2/
 282            {BASE}dir2/file
 283        */
 284       ASSERT (mkdir (BASE "dir", 0700) == 0);
 285       /* Files present here:
 286            {BASE}file
 287            {BASE}dir/
 288            {BASE}dir2/
 289            {BASE}dir2/file
 290        */
 291       {
 292         ASSERT (func (BASE "dir2/", BASE "dir") == 0);
 293         ASSERT (stat (BASE "dir/file", &st) == 0);
 294         errno = 0;
 295         ASSERT (stat (BASE "dir2", &st) == -1);
 296         ASSERT (errno == ENOENT);
 297       }
 298       /* Files present here:
 299            {BASE}file
 300            {BASE}dir/
 301            {BASE}dir/file
 302        */
 303       ASSERT (mkdir (BASE "dir2", 0700) == 0);
 304       /* Files present here:
 305            {BASE}file
 306            {BASE}dir/
 307            {BASE}dir/file
 308            {BASE}dir2/
 309        */
 310       {
 311         ASSERT (func (BASE "dir", BASE "dir2/") == 0);
 312         assert_nonexistent (BASE "dir");
 313         ASSERT (stat (BASE "dir2/file", &st) == 0);
 314       }
 315       /* Files present here:
 316            {BASE}file
 317            {BASE}dir2/
 318            {BASE}dir2/file
 319        */
 320       ASSERT (unlink (BASE "dir2/file") == 0);
 321     }
 322     /* Files present here:
 323          {BASE}file
 324          {BASE}dir2/
 325      */
 326     { /* Reject trailing dot.  */
 327       {
 328         errno = 0;
 329         ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
 330         ASSERT (errno == EINVAL || errno == ENOENT);
 331       }
 332       ASSERT (mkdir (BASE "dir", 0700) == 0);
 333       /* Files present here:
 334            {BASE}file
 335            {BASE}dir/
 336            {BASE}dir2/
 337        */
 338       {
 339         errno = 0;
 340         ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
 341         ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
 342                 || errno == ENOTEMPTY || errno == EEXIST
 343                 || errno == ENOENT /* WSL */);
 344       }
 345       {
 346         errno = 0;
 347         ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
 348         ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST
 349                 || errno == ENOENT /* WSL */);
 350       }
 351       ASSERT (rmdir (BASE "dir") == 0);
 352       /* Files present here:
 353            {BASE}file
 354            {BASE}dir2/
 355        */
 356       {
 357         errno = 0;
 358         ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
 359         ASSERT (errno == EINVAL || errno == ENOENT);
 360       }
 361       ASSERT (mkdir (BASE "dir", 0700) == 0);
 362       /* Files present here:
 363            {BASE}file
 364            {BASE}dir/
 365            {BASE}dir2/
 366        */
 367       {
 368         errno = 0;
 369         ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
 370         ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
 371                 || errno == ENOTEMPTY || errno == EEXIST
 372                 || errno == ENOENT /* WSL */);
 373       }
 374       {
 375         errno = 0;
 376         ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
 377         ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST
 378                 || errno == ENOENT /* WSL */);
 379       }
 380       ASSERT (rmdir (BASE "dir2") == 0);
 381       /* Files present here:
 382            {BASE}file
 383            {BASE}dir/
 384        */
 385     }
 386     { /* Move into subdir.  */
 387       {
 388         errno = 0;
 389         ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
 390         ASSERT (errno == EINVAL || errno == EACCES);
 391       }
 392       {
 393         errno = 0;
 394         ASSERT (stat (BASE "dir/sub", &st) == -1);
 395         ASSERT (errno == ENOENT);
 396       }
 397       ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
 398       /* Files present here:
 399            {BASE}file
 400            {BASE}dir/
 401            {BASE}dir/sub/
 402        */
 403       {
 404         errno = 0;
 405         ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
 406         ASSERT (errno == EINVAL);
 407         ASSERT (stat (BASE "dir/sub", &st) == 0);
 408       }
 409       ASSERT (rmdir (BASE "dir/sub") == 0);
 410     }
 411   }
 412   /* Files present here:
 413        {BASE}file
 414        {BASE}dir/
 415    */
 416 
 417   /* Mixing file and directory.  */
 418 
 419   {
 420     { /* File onto dir.  */
 421       {
 422         errno = 0;
 423         ASSERT (func (BASE "file", BASE "dir") == -1);
 424         ASSERT (errno == EISDIR || errno == ENOTDIR);
 425       }
 426       {
 427         errno = 0;
 428         ASSERT (func (BASE "file", BASE "dir/") == -1);
 429         ASSERT (errno == EISDIR || errno == ENOTDIR);
 430       }
 431     }
 432     { /* Dir onto file.  */
 433       {
 434         errno = 0;
 435         ASSERT (func (BASE "dir", BASE "file") == -1);
 436         ASSERT (errno == ENOTDIR);
 437       }
 438       {
 439         errno = 0;
 440         ASSERT (func (BASE "dir/", BASE "file") == -1);
 441         ASSERT (errno == ENOTDIR);
 442       }
 443     }
 444   }
 445 
 446   /* Hard links.  */
 447 
 448   { /* File onto self.  */
 449     ASSERT (func (BASE "file", BASE "file") == 0);
 450     memset (&st, 0, sizeof st);
 451     ASSERT (stat (BASE "file", &st) == 0);
 452     ASSERT (st.st_size == 2);
 453   }
 454   /* Files present here:
 455        {BASE}file
 456        {BASE}dir/
 457    */
 458   { /* Empty dir onto self.  */
 459     ASSERT (func (BASE "dir", BASE "dir") == 0);
 460     ASSERT (stat (BASE "dir", &st) == 0);
 461   }
 462   /* Files present here:
 463        {BASE}file
 464        {BASE}dir/
 465    */
 466   ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
 467   /* Files present here:
 468        {BASE}file
 469        {BASE}dir/
 470        {BASE}dir/file
 471    */
 472   { /* Full dir onto self.  */
 473     ASSERT (func (BASE "dir", BASE "dir") == 0);
 474   }
 475   ASSERT (unlink (BASE "dir/file") == 0);
 476   /* Files present here:
 477        {BASE}file
 478        {BASE}dir/
 479    */
 480   {
 481     /*  Not all file systems support link.  Mingw doesn't have
 482         reliable st_nlink on hard links, but our implementation does
 483         fail with EPERM on poor file systems, and we can detect the
 484         inferior stat() via st_ino.  Cygwin 1.5.x copies rather than
 485         links files on those file systems, but there, st_nlink and
 486         st_ino are reliable.  */
 487     int ret = link (BASE "file", BASE "file2");
 488     if (!ret)
 489       {
 490         memset (&st, 0, sizeof st);
 491         ASSERT (stat (BASE "file2", &st) == 0);
 492         if (st.st_ino && st.st_nlink != 2)
 493           {
 494             ASSERT (unlink (BASE "file2") == 0);
 495             errno = EPERM;
 496             ret = -1;
 497           }
 498       }
 499     if (ret == -1)
 500       {
 501         /* If the device does not support hard links, errno is
 502            EPERM on Linux, EOPNOTSUPP on FreeBSD.  */
 503         switch (errno)
 504           {
 505           case EPERM:
 506           case EOPNOTSUPP:
 507             if (print)
 508               fputs ("skipping test: "
 509                      "hard links not supported on this file system\n",
 510                      stderr);
 511             ASSERT (unlink (BASE "file") == 0);
 512             ASSERT (rmdir (BASE "dir") == 0);
 513             return 77;
 514           default:
 515             perror ("link");
 516             return 1;
 517           }
 518       }
 519     ASSERT (ret == 0);
 520   }
 521   /* Files present here:
 522        {BASE}file
 523        {BASE}file2       (hard link to file)
 524        {BASE}dir/
 525    */
 526   { /* File onto hard link.  */
 527     ASSERT (func (BASE "file", BASE "file2") == 0);
 528     memset (&st, 0, sizeof st);
 529     if (stat (BASE "file", &st) != 0)
 530       {
 531         /* This can happen on NetBSD.  */
 532         ASSERT (errno == ENOENT);
 533         ASSERT (link (BASE "file2", BASE "file") == 0);
 534         ASSERT (stat (BASE "file", &st) == 0);
 535       }
 536     ASSERT (st.st_size == 2);
 537     memset (&st, 0, sizeof st);
 538     ASSERT (stat (BASE "file2", &st) == 0);
 539     ASSERT (st.st_size == 2);
 540   }
 541   /* Files present here:
 542        {BASE}file
 543        {BASE}file2
 544        {BASE}dir/
 545    */
 546   ASSERT (unlink (BASE "file2") == 0);
 547   /* Files present here:
 548        {BASE}file
 549        {BASE}dir/
 550    */
 551 
 552   /* Symlinks.  */
 553 
 554   if (symlink (BASE "file", BASE "link1"))
 555     {
 556       if (print)
 557         fputs ("skipping test: symlinks not supported on this file system\n",
 558                stderr);
 559       ASSERT (unlink (BASE "file") == 0);
 560       ASSERT (rmdir (BASE "dir") == 0);
 561       return 77;
 562     }
 563   /* Files present here:
 564        {BASE}file
 565        {BASE}link1 -> {BASE}file
 566        {BASE}dir/
 567    */
 568   { /* Simple rename.  */
 569     ASSERT (func (BASE "link1", BASE "link2") == 0);
 570     ASSERT (stat (BASE "file", &st) == 0);
 571     errno = 0;
 572     ASSERT (lstat (BASE "link1", &st) == -1);
 573     ASSERT (errno == ENOENT);
 574     memset (&st, 0, sizeof st);
 575     ASSERT (lstat (BASE "link2", &st) == 0);
 576     ASSERT (S_ISLNK (st.st_mode));
 577   }
 578   /* Files present here:
 579        {BASE}file
 580        {BASE}link2 -> {BASE}file
 581        {BASE}dir/
 582    */
 583   { /* Overwrite.  */
 584     ASSERT (symlink (BASE "nowhere", BASE "link1") == 0);
 585     /* Files present here:
 586          {BASE}file
 587          {BASE}link1 -> {BASE}nowhere
 588          {BASE}link2 -> {BASE}file
 589          {BASE}dir/
 590      */
 591     {
 592       ASSERT (func (BASE "link2", BASE "link1") == 0);
 593       memset (&st, 0, sizeof st);
 594       ASSERT (stat (BASE "link1", &st) == 0);
 595       ASSERT (st.st_size == 2);
 596       errno = 0;
 597       ASSERT (lstat (BASE "link2", &st) == -1);
 598       ASSERT (errno == ENOENT);
 599     }
 600   }
 601   /* Files present here:
 602        {BASE}file
 603        {BASE}link1 -> {BASE}file
 604        {BASE}dir/
 605    */
 606   { /* Symlink loop.  */
 607     ASSERT (symlink (BASE "link2", BASE "link2") == 0);
 608     /* Files present here:
 609          {BASE}file
 610          {BASE}link1 -> {BASE}file
 611          {BASE}link2 -> {BASE}link2
 612          {BASE}dir/
 613      */
 614     {
 615       ASSERT (func (BASE "link2", BASE "link2") == 0);
 616     }
 617     {
 618       errno = 0;
 619       ASSERT (func (BASE "link2/", BASE "link2") == -1);
 620       ASSERT (errno == ELOOP || errno == ENOTDIR);
 621     }
 622     ASSERT (func (BASE "link2", BASE "link3") == 0);
 623     /* Files present here:
 624          {BASE}file
 625          {BASE}link1 -> {BASE}file
 626          {BASE}link3 -> {BASE}link2
 627          {BASE}dir/
 628      */
 629     ASSERT (unlink (BASE "link3") == 0);
 630   }
 631   /* Files present here:
 632        {BASE}file
 633        {BASE}link1 -> {BASE}file
 634        {BASE}dir/
 635    */
 636   { /* Dangling link.  */
 637     ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
 638     /* Files present here:
 639          {BASE}file
 640          {BASE}link1 -> {BASE}file
 641          {BASE}link2 -> {BASE}nowhere
 642          {BASE}dir/
 643      */
 644     {
 645       ASSERT (func (BASE "link2", BASE "link3") == 0);
 646       errno = 0;
 647       ASSERT (lstat (BASE "link2", &st) == -1);
 648       ASSERT (errno == ENOENT);
 649       memset (&st, 0, sizeof st);
 650       ASSERT (lstat (BASE "link3", &st) == 0);
 651     }
 652   }
 653   /* Files present here:
 654        {BASE}file
 655        {BASE}link1 -> {BASE}file
 656        {BASE}link3 -> {BASE}nowhere
 657        {BASE}dir/
 658    */
 659   { /* Trailing slash on dangling.  */
 660     {
 661       errno = 0;
 662       ASSERT (func (BASE "link3/", BASE "link2") == -1);
 663       ASSERT (errno == ENOENT || errno == ENOTDIR);
 664     }
 665     {
 666       errno = 0;
 667       ASSERT (func (BASE "link3", BASE "link2/") == -1);
 668       ASSERT (errno == ENOENT || errno == ENOTDIR);
 669     }
 670     {
 671       errno = 0;
 672       ASSERT (lstat (BASE "link2", &st) == -1);
 673       ASSERT (errno == ENOENT);
 674     }
 675     memset (&st, 0, sizeof st);
 676     ASSERT (lstat (BASE "link3", &st) == 0);
 677   }
 678   /* Files present here:
 679        {BASE}file
 680        {BASE}link1 -> {BASE}file
 681        {BASE}link3 -> {BASE}nowhere
 682        {BASE}dir/
 683    */
 684   { /* Trailing slash on link to file.  */
 685     {
 686       errno = 0;
 687       ASSERT (func (BASE "link1/", BASE "link2") == -1);
 688       ASSERT (errno == ENOTDIR);
 689     }
 690     {
 691       errno = 0;
 692       ASSERT (func (BASE "link1", BASE "link3/") == -1);
 693       ASSERT (errno == ENOENT || errno == ENOTDIR);
 694     }
 695   }
 696   /* Files present here:
 697        {BASE}file
 698        {BASE}link1 -> {BASE}file
 699        {BASE}link3 -> {BASE}nowhere
 700        {BASE}dir/
 701    */
 702 
 703   /* Mixing symlink and file.  */
 704 
 705   { /* File onto link.  */
 706     ASSERT (close (creat (BASE "file2", 0600)) == 0);
 707     /* Files present here:
 708          {BASE}file
 709          {BASE}file2
 710          {BASE}link1 -> {BASE}file
 711          {BASE}link3 -> {BASE}nowhere
 712          {BASE}dir/
 713      */
 714     {
 715       ASSERT (func (BASE "file2", BASE "link3") == 0);
 716       errno = 0;
 717       ASSERT (stat (BASE "file2", &st) == -1);
 718       ASSERT (errno == ENOENT);
 719       memset (&st, 0, sizeof st);
 720       ASSERT (lstat (BASE "link3", &st) == 0);
 721       ASSERT (S_ISREG (st.st_mode));
 722     }
 723     /* Files present here:
 724          {BASE}file
 725          {BASE}link1 -> {BASE}file
 726          {BASE}link3
 727          {BASE}dir/
 728      */
 729     ASSERT (unlink (BASE "link3") == 0);
 730   }
 731   /* Files present here:
 732        {BASE}file
 733        {BASE}link1 -> {BASE}file
 734        {BASE}dir/
 735    */
 736   { /* Link onto file.  */
 737     ASSERT (symlink (BASE "nowhere", BASE "link2") == 0);
 738     /* Files present here:
 739          {BASE}file
 740          {BASE}link1 -> {BASE}file
 741          {BASE}link2 -> {BASE}nowhere
 742          {BASE}dir/
 743      */
 744     ASSERT (close (creat (BASE "file2", 0600)) == 0);
 745     /* Files present here:
 746          {BASE}file
 747          {BASE}file2
 748          {BASE}link1 -> {BASE}file
 749          {BASE}link2 -> {BASE}nowhere
 750          {BASE}dir/
 751      */
 752     {
 753       ASSERT (func (BASE "link2", BASE "file2") == 0);
 754       errno = 0;
 755       ASSERT (lstat (BASE "link2", &st) == -1);
 756       ASSERT (errno == ENOENT);
 757       memset (&st, 0, sizeof st);
 758       ASSERT (lstat (BASE "file2", &st) == 0);
 759       ASSERT (S_ISLNK (st.st_mode));
 760     }
 761     /* Files present here:
 762          {BASE}file
 763          {BASE}file2 -> {BASE}nowhere
 764          {BASE}link1 -> {BASE}file
 765          {BASE}dir/
 766      */
 767     ASSERT (unlink (BASE "file2") == 0);
 768   }
 769   /* Files present here:
 770        {BASE}file
 771        {BASE}link1 -> {BASE}file
 772        {BASE}dir/
 773    */
 774   { /* Trailing slash.  */
 775     {
 776       errno = 0;
 777       ASSERT (func (BASE "file/", BASE "link1") == -1);
 778       ASSERT (errno == ENOTDIR);
 779     }
 780     {
 781       errno = 0;
 782       ASSERT (func (BASE "file", BASE "link1/") == -1);
 783       ASSERT (errno == ENOTDIR || errno == ENOENT);
 784     }
 785     {
 786       errno = 0;
 787       ASSERT (func (BASE "link1/", BASE "file") == -1);
 788       ASSERT (errno == ENOTDIR);
 789     }
 790     {
 791       errno = 0;
 792       ASSERT (func (BASE "link1", BASE "file/") == -1);
 793       ASSERT (errno == ENOTDIR || errno == ENOENT);
 794       memset (&st, 0, sizeof st);
 795       ASSERT (lstat (BASE "file", &st) == 0);
 796       ASSERT (S_ISREG (st.st_mode));
 797       memset (&st, 0, sizeof st);
 798       ASSERT (lstat (BASE "link1", &st) == 0);
 799       ASSERT (S_ISLNK (st.st_mode));
 800     }
 801   }
 802   /* Files present here:
 803        {BASE}file
 804        {BASE}link1 -> {BASE}file
 805        {BASE}dir/
 806    */
 807 
 808   /* Mixing symlink and directory.  */
 809 
 810   { /* Directory onto link.  */
 811     {
 812       errno = 0;
 813       ASSERT (func (BASE "dir", BASE "link1") == -1);
 814       ASSERT (errno == ENOTDIR);
 815     }
 816     {
 817       errno = 0;
 818       ASSERT (func (BASE "dir/", BASE "link1") == -1);
 819       ASSERT (errno == ENOTDIR);
 820     }
 821     {
 822       errno = 0;
 823       ASSERT (func (BASE "dir", BASE "link1/") == -1);
 824       ASSERT (errno == ENOTDIR);
 825     }
 826   }
 827   { /* Link onto directory.  */
 828     {
 829       errno = 0;
 830       ASSERT (func (BASE "link1", BASE "dir") == -1);
 831       ASSERT (errno == EISDIR || errno == ENOTDIR);
 832     }
 833     {
 834       errno = 0;
 835       ASSERT (func (BASE "link1", BASE "dir/") == -1);
 836       ASSERT (errno == EISDIR || errno == ENOTDIR);
 837     }
 838     {
 839       errno = 0;
 840       ASSERT (func (BASE "link1/", BASE "dir") == -1);
 841       ASSERT (errno == ENOTDIR);
 842       memset (&st, 0, sizeof st);
 843       ASSERT (lstat (BASE "link1", &st) == 0);
 844       ASSERT (S_ISLNK (st.st_mode));
 845       memset (&st, 0, sizeof st);
 846       ASSERT (lstat (BASE "dir", &st) == 0);
 847       ASSERT (S_ISDIR (st.st_mode));
 848     }
 849   }
 850   /* Files present here:
 851        {BASE}file
 852        {BASE}link1 -> {BASE}file
 853        {BASE}dir/
 854    */
 855 
 856   /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
 857      leave "link-to-dir" dangling, but GNU rejects this.  POSIX
 858      requires rename("dir","dangling/") to create the directory so
 859      that "dangling/" now resolves, but GNU rejects this.  While we
 860      prefer GNU behavior, we don't enforce it.  However, we do test
 861      that the system either follows POSIX in both cases, or follows
 862      GNU.  */
 863   {
 864     int result;
 865     ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
 866     /* Files present here:
 867          {BASE}file
 868          {BASE}link1 -> {BASE}file
 869          {BASE}link2 -> {BASE}dir2
 870          {BASE}dir/
 871      */
 872     errno = 0;
 873     result = func (BASE "dir", BASE "link2/");
 874     if (result == 0)
 875       {
 876         /* POSIX.  */
 877         errno = 0;
 878         ASSERT (lstat (BASE "dir", &st) == -1);
 879         ASSERT (errno == ENOENT);
 880         memset (&st, 0, sizeof st);
 881         ASSERT (lstat (BASE "dir2", &st) == 0);
 882         ASSERT (S_ISDIR (st.st_mode));
 883         memset (&st, 0, sizeof st);
 884         ASSERT (lstat (BASE "link2", &st) == 0);
 885         ASSERT (S_ISLNK (st.st_mode));
 886         /* Files present here:
 887              {BASE}file
 888              {BASE}link1 -> {BASE}file
 889              {BASE}link2 -> {BASE}dir2
 890              {BASE}dir2/
 891          */
 892         {
 893           ASSERT (func (BASE "link2/", BASE "dir") == 0);
 894           memset (&st, 0, sizeof st);
 895           ASSERT (lstat (BASE "dir", &st) == 0);
 896           ASSERT (S_ISDIR (st.st_mode));
 897           errno = 0;
 898           ASSERT (lstat (BASE "dir2", &st) == -1);
 899           ASSERT (errno == ENOENT);
 900           memset (&st, 0, sizeof st);
 901           ASSERT (lstat (BASE "link2", &st) == 0);
 902           ASSERT (S_ISLNK (st.st_mode));
 903         }
 904       }
 905     else
 906       {
 907         /* GNU.  */
 908         ASSERT (result == -1);
 909         ASSERT (errno == ENOTDIR);
 910         memset (&st, 0, sizeof st);
 911         ASSERT (lstat (BASE "dir", &st) == 0);
 912         ASSERT (S_ISDIR (st.st_mode));
 913         errno = 0;
 914         ASSERT (lstat (BASE "dir2", &st) == -1);
 915         ASSERT (errno == ENOENT);
 916         memset (&st, 0, sizeof st);
 917         ASSERT (lstat (BASE "link2", &st) == 0);
 918         ASSERT (S_ISLNK (st.st_mode));
 919         ASSERT (unlink (BASE "link2") == 0);
 920         ASSERT (symlink (BASE "dir", BASE "link2") == 0);
 921         /* Files present here:
 922              {BASE}file
 923              {BASE}link1 -> {BASE}file
 924              {BASE}link2 -> {BASE}dir
 925              {BASE}dir/
 926          */
 927         errno = 0; /* OpenBSD notices that link2/ and dir are the same.  */
 928         result = func (BASE "link2/", BASE "dir");
 929         if (result) /* GNU/Linux rejects attempts to use link2/.  */
 930           {
 931             ASSERT (result == -1);
 932             ASSERT (errno == ENOTDIR || errno == EISDIR);
 933           }
 934         memset (&st, 0, sizeof st);
 935         ASSERT (lstat (BASE "dir", &st) == 0);
 936         ASSERT (S_ISDIR (st.st_mode));
 937         errno = 0;
 938         ASSERT (lstat (BASE "dir2", &st) == -1);
 939         ASSERT (errno == ENOENT);
 940         memset (&st, 0, sizeof st);
 941         ASSERT (lstat (BASE "link2", &st) == 0);
 942         ASSERT (S_ISLNK (st.st_mode));
 943       }
 944   }
 945   /* Files present here:
 946        {BASE}file
 947        {BASE}link1 -> {BASE}file
 948        {BASE}link2 -> {BASE}dir or {BASE}dir2
 949        {BASE}dir/
 950    */
 951 
 952   /* Clean up.  */
 953   ASSERT (unlink (BASE "file") == 0);
 954   ASSERT (rmdir (BASE "dir") == 0);
 955   ASSERT (unlink (BASE "link1") == 0);
 956   ASSERT (unlink (BASE "link2") == 0);
 957 
 958   return 0;
 959 }

/* [previous][next][first][last][top][bottom][index][help] */