(root)/
coreutils-9.4/
gnulib-tests/
test-remove.c
       1  /* Tests of remove.
       2     Copyright (C) 2009-2023 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  /* Written by Eric Blake <ebb9@byu.net>, 2009.  */
      18  
      19  #include <config.h>
      20  
      21  #include <stdio.h>
      22  
      23  #include "signature.h"
      24  SIGNATURE_CHECK (remove, int, (char const *));
      25  
      26  #include <fcntl.h>
      27  #include <errno.h>
      28  #include <stdlib.h>
      29  #include <string.h>
      30  #include <sys/stat.h>
      31  #include <unistd.h>
      32  
      33  #include "ignore-value.h"
      34  #include "macros.h"
      35  
      36  #define BASE "test-remove.t"
      37  
      38  int
      39  main (void)
      40  {
      41    /* Remove any leftovers from a previous partial run.  */
      42    ignore_value (system ("rm -rf " BASE "*"));
      43  
      44    /* Setup.  */
      45    ASSERT (mkdir (BASE "dir", 0700) == 0);
      46    ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
      47  
      48    /* Basic error conditions.  */
      49    errno = 0;
      50    ASSERT (remove ("") == -1);
      51    ASSERT (errno == ENOENT);
      52    errno = 0;
      53    ASSERT (remove ("nosuch") == -1);
      54    ASSERT (errno == ENOENT);
      55    errno = 0;
      56    ASSERT (remove ("nosuch/") == -1);
      57    ASSERT (errno == ENOENT);
      58    errno = 0;
      59    ASSERT (remove (".") == -1);
      60    ASSERT (errno == EINVAL || errno == EBUSY);
      61    /* Resulting errno after ".." or "/" is too varied to test; it is
      62       reasonable to see any of EINVAL, EEXIST, ENOTEMPTY, EACCES.  */
      63    ASSERT (remove ("..") == -1);
      64    ASSERT (remove ("/") == -1);
      65    ASSERT (remove ("///") == -1);
      66    errno = 0;
      67    ASSERT (remove (BASE "dir/file/") == -1);
      68    ASSERT (errno == ENOTDIR);
      69  
      70    /* Non-empty directory.  */
      71    errno = 0;
      72    ASSERT (remove (BASE "dir") == -1);
      73    ASSERT (errno == EEXIST || errno == ENOTEMPTY);
      74  
      75    /* Non-directory.  */
      76    ASSERT (remove (BASE "dir/file") == 0);
      77  
      78    /* Empty directory.  */
      79    errno = 0;
      80    ASSERT (remove (BASE "dir/.//") == -1);
      81    ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
      82    ASSERT (remove (BASE "dir") == 0);
      83  
      84    /* Test symlink behavior.  Specifying trailing slash should remove
      85       referent directory, or cause ENOTDIR failure, but not touch
      86       symlink.  */
      87    if (symlink (BASE "dir", BASE "link") != 0)
      88      {
      89        fputs ("skipping test: symlinks not supported on this file system\n",
      90               stderr);
      91        return 77;
      92      }
      93    ASSERT (mkdir (BASE "dir", 0700) == 0);
      94    errno = 0;
      95    if (remove (BASE "link/") == 0)
      96      {
      97        struct stat st;
      98        errno = 0;
      99        ASSERT (stat (BASE "link", &st) == -1);
     100        ASSERT (errno == ENOENT);
     101      }
     102    else
     103      ASSERT (remove (BASE "dir") == 0);
     104    {
     105      struct stat st;
     106      ASSERT (lstat (BASE "link", &st) == 0);
     107      ASSERT (S_ISLNK (st.st_mode));
     108    }
     109    ASSERT (remove (BASE "link") == 0);
     110    /* Trailing slash on symlink to non-directory is an error.  */
     111    ASSERT (symlink (BASE "loop", BASE "loop") == 0);
     112    errno = 0;
     113    ASSERT (remove (BASE "loop/") == -1);
     114    ASSERT (errno == ELOOP || errno == ENOTDIR);
     115    ASSERT (remove (BASE "loop") == 0);
     116    ASSERT (close (creat (BASE "file", 0600)) == 0);
     117    ASSERT (symlink (BASE "file", BASE "link") == 0);
     118    errno = 0;
     119    ASSERT (remove (BASE "link/") == -1);
     120    ASSERT (errno == ENOTDIR);
     121    ASSERT (remove (BASE "link") == 0);
     122    ASSERT (remove (BASE "file") == 0);
     123  
     124    return 0;
     125  }