root/user/testbin/rmdirtest/rmdirtest.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. startup
  2. killdir
  3. finish
  4. test1
  5. test2
  6. test3
  7. test4
  8. test5
  9. test6
  10. test7
  11. main

   1 /*
   2  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
   3  *      The President and Fellows of Harvard College.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the University nor the names of its contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * rmdirtest.c
  32  *
  33  *      Tests file system synchronization and directory implementation by
  34  *      removing the current directory under itself and then trying to do
  35  *      things. It's ok for most of those things to fail, but the system
  36  *      shouldn't crash.
  37  */
  38 
  39 #include <sys/types.h>
  40 #include <sys/stat.h>
  41 #include <stdio.h>
  42 #include <string.h>
  43 #include <unistd.h>
  44 #include <fcntl.h>
  45 #include <errno.h>
  46 #include <limits.h>
  47 #include <err.h>
  48 
  49 
  50 static const char testdir[] = "testdir";
  51 static char startpoint[PATH_MAX - sizeof(testdir)];
  52 
  53 /*
  54  * Create the test directory, and change into it, remembering
  55  * where we came from.
  56  */
  57 
  58 static
  59 void
  60 startup(void)
  61 {
  62         if (getcwd(startpoint, sizeof(startpoint))==NULL) {
  63                 err(1, "getcwd (not in test dir)");
  64         }
  65 
  66         if (mkdir(testdir, 0775) < 0) {
  67                 err(1, "%s: mkdir", testdir);
  68         }
  69 
  70         if (chdir(testdir) < 0) {
  71                 err(1, "%s: chdir", testdir);
  72         }
  73 }
  74 
  75 /*
  76  * Remove the test directory.
  77  *
  78  * Note that even though it's the current directory, we can't do it
  79  * with rmdir(".") - what that would try to do is remove the "." entry
  80  * from the current directory, which is justifiably prohibited.
  81  */
  82 
  83 static
  84 void
  85 killdir(void)
  86 {
  87         char tmp[PATH_MAX];
  88 
  89         snprintf(tmp, sizeof(tmp), "%s/%s", startpoint, testdir);
  90         if (rmdir(tmp)<0) {
  91                 err(1, "%s: rmdir", tmp);
  92         }
  93 }
  94 
  95 /*
  96  * Leave the test directory and go back to where we came from, so we
  97  * can try again.
  98  */
  99 
 100 static
 101 void
 102 finish(void)
 103 {
 104         if (chdir(startpoint)<0) {
 105                 err(1, "%s: chdir", startpoint);
 106         }
 107 }
 108 
 109 /*************************************************************/
 110 
 111 /*
 112  * Basic test - just try removing the directory without doing anything
 113  * evil.
 114  */
 115 static
 116 void
 117 test1(void)
 118 {
 119         printf("Making %s\n", testdir);
 120         startup();
 121 
 122         printf("Removing %s while in it\n", testdir);
 123         killdir();
 124 
 125         printf("Leaving the test directory\n");
 126         finish();
 127 }
 128 
 129 /*
 130  * Now do it while we also have the directory open.
 131  */
 132 
 133 static
 134 void
 135 test2(void)
 136 {
 137         int fd;
 138 
 139         printf("Now trying with the directory open...\n");
 140         startup();
 141         fd = open(".", O_RDONLY);
 142         if (fd<0) {
 143                 err(1, ".: open");
 144         }
 145         killdir();
 146         finish();
 147 
 148         /* close *after* leaving, just for excitement */
 149         if (close(fd)<0) {
 150                 err(1, "removed %s: close", testdir);
 151         }
 152 }
 153 
 154 /*
 155  * Now see if . and .. work after rmdir.
 156  */
 157 
 158 static
 159 void
 160 test3(void)
 161 {
 162         char buf[PATH_MAX];
 163         int fd;
 164 
 165         printf("Checking if . exists after rmdir\n");
 166         startup();
 167         killdir();
 168 
 169         fd = open(".", O_RDONLY);
 170         if (fd<0) {
 171                 switch (errno) {
 172                     case EINVAL:
 173                     case EIO:
 174                     case ENOENT:
 175                         break;
 176                     default:
 177                         err(1, ".");
 178                         break;
 179                 }
 180         }
 181         else {
 182                 close(fd);
 183         }
 184 
 185         fd = open("..", O_RDONLY);
 186         if (fd<0) {
 187                 switch (errno) {
 188                     case EINVAL:
 189                     case EIO:
 190                     case ENOENT:
 191                         break;
 192                     default:
 193                         err(1, "..");
 194                         break;
 195                 }
 196         }
 197         else {
 198                 warnx("..: openable after rmdir - might be bad");
 199                 close(fd);
 200         }
 201 
 202         snprintf(buf, sizeof(buf), "../%s", testdir);
 203         fd = open(buf, O_RDONLY);
 204         if (fd<0) {
 205                 switch (errno) {
 206                     case EINVAL:
 207                     case EIO:
 208                     case ENOENT:
 209                         break;
 210                     default:
 211                         err(1, "%s", buf);
 212                         break;
 213                 }
 214         }
 215         else {
 216                 errx(1, "%s: works after rmdir", buf);
 217         }
 218 
 219         finish();
 220 }
 221 
 222 /*
 223  * Now try to create files.
 224  */
 225 
 226 static
 227 void
 228 test4(void)
 229 {
 230         char buf[4096];
 231         int fd;
 232 
 233         printf("Checking if creating files works after rmdir...\n");
 234         startup();
 235         killdir();
 236 
 237         fd = open("newfile", O_WRONLY|O_CREAT|O_TRUNC, 0664);
 238         if (fd<0) {
 239                 switch (errno) {
 240                     case EINVAL:
 241                     case EIO:
 242                     case ENOENT:
 243                         break;
 244                     default:
 245                         err(1, "%s", buf);
 246                         break;
 247                 }
 248         }
 249         else {
 250                 warnx("newfile: creating files after rmdir works");
 251                 warnx("(this is only ok if the space gets reclaimed)");
 252 
 253                 /*
 254                  * Waste a bunch of space so we'll be able to tell
 255                  */
 256                 memset(buf, 'J', sizeof(buf));
 257                 write(fd, buf, sizeof(buf));
 258                 write(fd, buf, sizeof(buf));
 259                 write(fd, buf, sizeof(buf));
 260                 write(fd, buf, sizeof(buf));
 261                 close(fd);
 262         }
 263 
 264         finish();
 265 }
 266 
 267 /*
 268  * Now try to create directories.
 269  */
 270 
 271 static
 272 void
 273 test5(void)
 274 {
 275         printf("Checking if creating subdirs works after rmdir...\n");
 276         startup();
 277         killdir();
 278 
 279         if (mkdir("newdir", 0775)<0) {
 280                 switch (errno) {
 281                     case EINVAL:
 282                     case EIO:
 283                     case ENOENT:
 284                         break;
 285                     default:
 286                         err(1, "mkdir in removed dir");
 287                         break;
 288                 }
 289         }
 290         else {
 291                 warnx("newfile: creating directories after rmdir works");
 292                 warnx("(this is only ok if the space gets reclaimed)");
 293 
 294                 /*
 295                  * Waste a bunch of space so we'll be able to tell
 296                  */
 297                 mkdir("newdir/t0", 0775);
 298                 mkdir("newdir/t1", 0775);
 299                 mkdir("newdir/t2", 0775);
 300                 mkdir("newdir/t3", 0775);
 301                 mkdir("newdir/t4", 0775);
 302                 mkdir("newdir/t5", 0775);
 303         }
 304 
 305         finish();
 306 }
 307 
 308 /*
 309  * Now try listing the directory.
 310  */
 311 static
 312 void
 313 test6(void)
 314 {
 315         char buf[PATH_MAX];
 316         int fd, len;
 317 
 318         printf("Now trying to list the directory...\n");
 319         startup();
 320         fd = open(".", O_RDONLY);
 321         if (fd<0) {
 322                 err(1, ".: open");
 323         }
 324         killdir();
 325 
 326         while ((len = getdirentry(fd, buf, sizeof(buf)-1))>0) {
 327                 if ((unsigned)len >= sizeof(buf)-1) {
 328                         errx(1, ".: getdirentry: returned invalid length");
 329                 }
 330                 buf[len] = 0;
 331                 if (!strcmp(buf, ".") || !strcmp(buf, "..")) {
 332                         /* these are allowed to appear */
 333                         continue;
 334                 }
 335                 errx(1, ".: getdirentry: returned unexpected name %s", buf);
 336         }
 337         if (len==0) {
 338                 /* EOF - ok */
 339         }
 340         else { /* len < 0 */
 341                 switch (errno) {
 342                     case EINVAL:
 343                     case EIO:
 344                         break;
 345                     default:
 346                         err(1, ".: getdirentry");
 347                         break;
 348                 }
 349         }
 350 
 351         finish();
 352 
 353         /* close *after* leaving, just for excitement */
 354         if (close(fd)<0) {
 355                 err(1, "removed %s: close", testdir);
 356         }
 357 }
 358 
 359 /*
 360  * Try getcwd.
 361  */
 362 static
 363 void
 364 test7(void)
 365 {
 366         char buf[PATH_MAX];
 367 
 368         startup();
 369         killdir();
 370         if (getcwd(buf, sizeof(buf))==NULL) {
 371                 switch (errno) {
 372                     case EINVAL:
 373                     case EIO:
 374                     case ENOENT:
 375                         break;
 376                     default:
 377                         err(1, "getcwd after removing %s", testdir);
 378                         break;
 379                 }
 380         }
 381         else {
 382                 errx(1, "getcwd after removing %s: succeeded (got %s)",
 383                      testdir, buf);
 384         }
 385 
 386         finish();
 387 }
 388 
 389 /**************************************************************/
 390 
 391 int
 392 main(void)
 393 {
 394         test1();
 395         test2();
 396         test3();
 397         test4();
 398         test5();
 399         test6();
 400         test7();
 401 
 402         printf("Whew... survived.\n");
 403         return 0;
 404 }

/* [<][>][^][v][top][bottom][index][help] */