├── .gitignore ├── LICENCE.GPL ├── Makefile ├── README ├── context.py ├── direct.py ├── mount_union.py ├── remount_union.py ├── run ├── set_up.py ├── settings.py ├── tests ├── dir-open-dir.py ├── dir-open.py ├── dir-sym1-open.py ├── dir-sym1-weird-open.py ├── dir-sym2-open.py ├── dir-sym2-weird-open.py ├── dir-weird-open-dir.py ├── dir-weird-open.py ├── hard-link-dir.py ├── hard-link-sym.py ├── hard-link.py ├── impermissible.py ├── mkdir.py ├── noent-creat-excl-trunc.py ├── noent-creat-excl.py ├── noent-creat-trunc.py ├── noent-creat.py ├── noent-plain.py ├── noent-trunc.py ├── open-creat-excl-trunc.py ├── open-creat-excl.py ├── open-creat-trunc.py ├── open-creat.py ├── open-plain.py ├── open-trunc.py ├── readlink.py ├── rename-dir.py ├── rename-empty-dir.py ├── rename-exdev.py ├── rename-file.py ├── rename-hard-link.py ├── rename-mass-2.py ├── rename-mass-3.py ├── rename-mass-4.py ├── rename-mass-5.py ├── rename-mass-dir.py ├── rename-mass-sym.py ├── rename-mass.py ├── rename-move-dir.py ├── rename-new-dir.py ├── rename-new-pop-dir.py ├── rename-pop-dir.py ├── rmdir.py ├── rmtree-new.py ├── rmtree.py ├── sym1-creat-excl.py ├── sym1-creat.py ├── sym1-plain.py ├── sym1-trunc.py ├── sym2-creat-excl.py ├── sym2-creat.py ├── sym2-plain.py ├── sym2-trunc.py ├── symx-creat-excl.py ├── symx-creat-trunc.py ├── symx-creat.py ├── symx-plain.py ├── symx-trunc.py ├── truncate.py └── unlink.py ├── tool_box.py └── unmount_union.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | fs-op 3 | open-file 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @echo Nothing to do 3 | 4 | clean: 5 | $(RM) *~ tests/*~ 6 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | To run these tests: 2 | 3 | If testing overlayfs, do: 4 | 5 | ./run --ov 6 | 7 | To run the tests with nested overlayfs, do: 8 | 9 | ./run --ovov 10 | 11 | To run the tests without any unioning, do: 12 | 13 | ./run --no 14 | 15 | To just set up the environment and exit without doing any tests, 16 | add the -s flag, e.g.: 17 | 18 | ./run --ov -s 19 | 20 | To run overlayfs tests with all layers on the same underlying fs, 21 | add the --samefs flag, e.g.: 22 | 23 | ./run --ov --samefs 24 | 25 | To run overlayfs tests with lower layer on a squashfs image, 26 | add the --squashfs flag, e.g.: 27 | 28 | ./run --ov --squashfs 29 | 30 | To run overlayfs tests with up to N middle layers, do: 31 | 32 | ./run --ov= 33 | 34 | The run will start with two layers and during some tests, upper layer 35 | will be rotated to the top of the lower layer stack and a new upper 36 | layer will be created. 37 | 38 | To run overlayfs tests with up to N middle layers, M middle layers on 39 | unique underlying filesystems, do: 40 | 41 | ./run --ov= --maxfs= 42 | 43 | The first M rotations will create a new filesystem as the upper layer. 44 | 45 | To run the tests using a FUSE overlay file system implementation: 46 | 47 | ./run --ov --fuse= 48 | 49 | 50 | The following environment variables are supported: 51 | 52 | UNIONMOUNT_BASEDIR - parent dir of all samefs layers (default: /base) 53 | UNIONMOUNT_LOWERDIR - lower layer path for non samefs (default: /lower) 54 | UNIONMOUNT_MNTPOINT - mount point for executing tests (default: /mnt) 55 | 56 | When user provides UNIONMOUNT_LOWERDIR: 57 | 58 | 1) Path should be an existing directory whose content will be deleted. 59 | 2) Path is assumed to be on a different filesystem than base dir, so 60 | --samefs setup is not supported. 61 | 62 | When user provides UNIONMOUNT_BASEDIR: 63 | 64 | 1) Path should be an existing directory whose content will be deleted. 65 | 2) Upper layer and middle layers will be created under base dir. 66 | 3) If UNIONMOUNT_MNTPOINT is not provided, the overlay mount point will 67 | be created under base dir. 68 | 4) If UNIONMOUNT_LOWERDIR is not provided, the lower layer dir will be 69 | created under base dir. 70 | 5) If UNIONMOUNT_LOWERDIR is not provided, the test setup defaults to 71 | --samefs (i.e. lower and upper layers are on the same base fs). 72 | However, if --maxfs= is specified, a tmpfs instance will be mounted 73 | on the lower layer dir that was created under base dir. 74 | 75 | 76 | For more advanced overlayfs test options and more examples, see: 77 | https://github.com/amir73il/overlayfs/wiki/Overlayfs-testing 78 | -------------------------------------------------------------------------------- /direct.py: -------------------------------------------------------------------------------- 1 | from tool_box import ArgumentError 2 | from context import test_context 3 | import argparse 4 | import errno 5 | 6 | def parse_C_int(s): 7 | try: 8 | if s.startswith("0x"): 9 | return int(s[2:], 16) 10 | elif s.startswith("0"): 11 | return int(s[2:], 8) 12 | else: 13 | return int(s[2:], 10) 14 | except ValueError: 15 | raise ArgumentError("Unparseable number '" + s + "'") 16 | 17 | ############################################################################### 18 | # 19 | # ./run --open-file [-acdertvw] [-W ] [-R ] [-B] [-E ] 20 | # 21 | ############################################################################### 22 | def direct_open_file(cfg, cmdargs): 23 | if len(cmdargs) < 1: 24 | raise ArgumentError("Insufficient Arguments") 25 | 26 | parser = argparse.ArgumentParser(description='Open and read/write a file', 27 | prog=cfg.progname() + " --open-file ") 28 | parser.add_argument("file", nargs=1) 29 | parser.add_argument("-a", action="store_true") 30 | parser.add_argument("-c", action="store_true") 31 | parser.add_argument("-d", action="store_true") 32 | parser.add_argument("-e", action="store_true") 33 | parser.add_argument("-m", nargs=1) 34 | parser.add_argument("-r", action="store_true") 35 | parser.add_argument("-t", action="store_true") 36 | parser.add_argument("-v", action="store_true") 37 | parser.add_argument("-w", action="store_true") 38 | parser.add_argument("-W", nargs=1) 39 | parser.add_argument("-R", nargs=1) 40 | parser.add_argument("-B", action="store_true") 41 | parser.add_argument("-E", nargs=1) 42 | p = parser.parse_args(cmdargs) 43 | p = vars(p) 44 | 45 | args = dict() 46 | if p["r"]: 47 | if p["w"]: 48 | args["rw"] = 1 49 | else: 50 | args["ro"] = 1 51 | elif p["w"]: 52 | args["wo"] = 1 53 | 54 | if p["v"]: 55 | ctx.cfg.set_verbose() 56 | if p["c"]: 57 | args["crt"] = 1 58 | if p["d"]: 59 | args["dir"] = 1 60 | if p["e"]: 61 | args["ex"] = 1 62 | if p["m"] != None: 63 | args["mode"] = parse_C_int(p["m"][0]) 64 | if p["t"]: 65 | args["tr"] = 1 66 | if p["B"]: 67 | args["as_bin"] = 1 68 | if p["R"]: 69 | args["read"] = p["R"][0] 70 | if p["W"]: 71 | args["write"] = p["W"][0] 72 | 73 | if p["E"]: 74 | errname = p["E"][0] 75 | for i in errno.errorcode.keys(): 76 | if errno.errorcode[i] == errname: 77 | args["err"] = i 78 | break 79 | else: 80 | raise ArgumentError("Unknown error code name '" + errname + "'") 81 | 82 | ctx = test_context(cfg, direct_mode=True) 83 | ctx.open_file(p["file"][0], **args) 84 | 85 | ############################################################################### 86 | # 87 | # ./run --fs-op [*] [-aLlv] [-R ] [-B] [-E ] 88 | # 89 | ############################################################################### 90 | def direct_fs_op(cfg, cmdargs): 91 | ctx = test_context(cfg, direct_mode=True) 92 | if len(cmdargs) < 2: 93 | raise ArgumentError("Insufficient Arguments") 94 | 95 | op = cmdargs[0][2:] 96 | parser = argparse.ArgumentParser(description='Operate upon a file', 97 | prog=cfg.progname() + " --" + op + " [+]") 98 | parser.add_argument("file", nargs=1) 99 | parser.add_argument("args", nargs="*") 100 | parser.add_argument("-v", action="store_true") 101 | parser.add_argument("-a", action="store_true") 102 | parser.add_argument("-l", action="store_true") 103 | parser.add_argument("-L", action="store_true") 104 | parser.add_argument("-R", nargs=1) 105 | parser.add_argument("-B", action="store_true") 106 | parser.add_argument("-E", nargs=1) 107 | p = parser.parse_args(cmdargs[1:]) 108 | p = vars(p) 109 | 110 | args = dict() 111 | if p["v"]: 112 | ctx.cfg.set_verbose() 113 | if p["a"]: 114 | args["no_automount"] = 1 115 | if p["l"]: 116 | args["no_follow"] = 1 117 | if p["L"]: 118 | args["follow"] = 1 119 | if p["R"]: 120 | args["content"] = p["R"][0] 121 | if p["B"]: 122 | args["as_bin"] = 1 123 | 124 | if p["E"]: 125 | errname = p["E"][0] 126 | for i in errno.errorcode.keys(): 127 | if errno.errorcode[i] == errname: 128 | args["err"] = i 129 | break 130 | else: 131 | raise ArgumentError("Unknown error code name '" + errname + "'") 132 | 133 | ctx = test_context(cfg, direct_mode=True) 134 | 135 | f = p["file"][0] 136 | xargs = p["args"] 137 | if op == "chmod": 138 | if len(xargs) != 1: 139 | raise ArgumentError("chmod requires a single mode argument") 140 | ctx.chmod(f, parse_C_int(xargs[0]), **args) 141 | elif op == "link": 142 | if len(xargs) != 1: 143 | raise ArgumentError("link requires a single additional filename") 144 | ctx.rename(f, xargs[0], **args) 145 | elif op == "mkdir": 146 | if len(xargs) != 1: 147 | raise ArgumentError("mkdir requires a single mode argument") 148 | ctx.mkdir(f, parse_C_int(xargs[0]), **args) 149 | elif op == "readlink": 150 | if len(xargs) != 0: 151 | raise ArgumentError("readlink requires no additional arguments") 152 | ctx.readlink(f, **args) 153 | elif op == "rename": 154 | if len(xargs) != 1: 155 | raise ArgumentError("rename requires a single additional filename") 156 | ctx.rename(f, xargs[0], **args) 157 | elif op == "rmdir": 158 | if len(xargs) != 0: 159 | raise ArgumentError("rmdir requires no additional arguments") 160 | ctx.rmdir(f, **args) 161 | elif op == "truncate": 162 | if len(xargs) != 1: 163 | raise ArgumentError("truncate requires a single size argument") 164 | ctx.truncate(f, int(xargs[0]), **args) 165 | elif op == "unlink": 166 | if len(xargs) != 0: 167 | raise ArgumentError("unlink requires no additional arguments") 168 | ctx.unlink(f, **args) 169 | elif op == "utimes": 170 | if len(xargs) != 0: 171 | raise ArgumentError("utimes requires no additional arguments") 172 | ctx.utimes(f, **args) 173 | else: 174 | raise ArgumentError("Unknown subcommand") 175 | -------------------------------------------------------------------------------- /mount_union.py: -------------------------------------------------------------------------------- 1 | from tool_box import * 2 | 3 | def mount_union(ctx): 4 | cfg = ctx.config() 5 | union_mntroot = cfg.union_mntroot() 6 | testdir = cfg.testdir() 7 | if cfg.testing_none(): 8 | lower_mntroot = cfg.lower_mntroot() 9 | system("mount -o bind " + lower_mntroot + " " + union_mntroot) 10 | ctx.note_upper_fs(lower_mntroot, testdir, testdir) 11 | 12 | else: 13 | lower_mntroot = cfg.lower_mntroot() 14 | upper_mntroot = cfg.upper_mntroot() 15 | if cfg.should_mount_upper(): 16 | system("mount " + upper_mntroot + " 2>/dev/null" 17 | " || mount -t tmpfs upper_layer " + upper_mntroot) 18 | layer_mntroot = upper_mntroot + "/" + ctx.curr_layer() 19 | upperdir = layer_mntroot + "/u" 20 | workdir = layer_mntroot + "/w" 21 | nested_mntroot = upper_mntroot + "/n" 22 | nested_upper = upper_mntroot + "/u" 23 | nested_work = upper_mntroot + "/w" 24 | try: 25 | os.mkdir(layer_mntroot) 26 | if cfg.is_nested(): 27 | os.mkdir(nested_mntroot) 28 | except OSError: 29 | system("rm -rf " + upper_mntroot + "/*") 30 | os.mkdir(layer_mntroot) 31 | if cfg.is_nested(): 32 | os.mkdir(nested_mntroot) 33 | # Create unique fs for upper/0 if maxfs > 0 34 | if cfg.maxfs() > 0: 35 | system("mount -t tmpfs " + ctx.curr_layer() + "_layer " + layer_mntroot) 36 | os.mkdir(upperdir) 37 | os.mkdir(workdir) 38 | # Create pure upper file 39 | write_file(upperdir + "/f", "pure"); 40 | if cfg.is_nested(): 41 | os.mkdir(nested_upper) 42 | os.mkdir(nested_work) 43 | 44 | mntopt = cfg.mntopts() 45 | if cfg.is_nested(): 46 | nested_mntopt = mntopt 47 | if cfg.is_verify(): 48 | nested_mntopt = mntopt + ",metacopy=off,nfs_export=on" 49 | system("mount -t " + cfg.fstype() + " nested_layer " + nested_mntroot + " " + nested_mntopt + " -olowerdir=" + lower_mntroot + ",upperdir=" + nested_upper + ",workdir=" + nested_work) 50 | lower_mntroot = nested_mntroot 51 | ctx.note_lower_fs(lower_mntroot) 52 | system("mount -t " + cfg.fstype() + " " + cfg.fsname() + " " + union_mntroot + " " + mntopt + " -olowerdir=" + lower_mntroot + ",upperdir=" + upperdir + ",workdir=" + workdir) 53 | # Record st_dev of merge dir and pure upper file 54 | ctx.note_upper_fs(upper_mntroot, testdir, union_mntroot + "/f") 55 | ctx.note_lower_layers(lower_mntroot) 56 | ctx.note_upper_layer(upperdir) 57 | -------------------------------------------------------------------------------- /remount_union.py: -------------------------------------------------------------------------------- 1 | from tool_box import * 2 | 3 | def remount_union(ctx, rotate_upper=False): 4 | cfg = ctx.config() 5 | union_mntroot = cfg.union_mntroot() 6 | 7 | if cfg.testing_overlayfs(): 8 | system("umount " + cfg.union_mntroot()) 9 | system("echo 3 > /proc/sys/vm/drop_caches") 10 | check_not_tainted() 11 | 12 | upper_mntroot = cfg.upper_mntroot() 13 | if rotate_upper and ctx.have_more_layers(): 14 | lowerlayers = ctx.upper_layer() + ":" + ctx.lower_layers() 15 | layer_mntroot = upper_mntroot + "/" + ctx.next_layer() 16 | upperdir = layer_mntroot + "/u" 17 | workdir = layer_mntroot + "/w" 18 | os.mkdir(layer_mntroot) 19 | # Create unique fs for upper/N if N < maxfs 20 | if ctx.have_more_fs(): 21 | system("mount -t tmpfs " + ctx.curr_layer() + "_layer " + layer_mntroot) 22 | os.mkdir(upperdir) 23 | os.mkdir(workdir) 24 | # Create pure upper file 25 | write_file(upperdir + "/f", "pure"); 26 | else: 27 | lowerlayers = ctx.lower_layers() 28 | layer_mntroot = upper_mntroot + "/" + ctx.curr_layer() 29 | upperdir = layer_mntroot + "/u" 30 | workdir = layer_mntroot + "/w" 31 | 32 | mnt = union_mntroot 33 | mntopt = cfg.mntopts() 34 | cmd = "mount -t " + cfg.fstype() + " " + cfg.fsname() + " " + mnt + " " + mntopt + " -olowerdir=" + lowerlayers + ",upperdir=" + upperdir + ",workdir=" + workdir 35 | system(cmd) 36 | if cfg.is_verbose(): 37 | write_kmsg(cmd); 38 | # Record st_dev of merge dir and pure upper file 39 | ctx.note_upper_fs(upper_mntroot, cfg.testdir(), union_mntroot + "/f") 40 | ctx.note_lower_layers(lowerlayers) 41 | ctx.note_upper_layer(upperdir) 42 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys, os, types, inspect 4 | from settings import config 5 | from context import test_context 6 | from tool_box import * 7 | from set_up import * 8 | from mount_union import mount_union 9 | from unmount_union import unmount_union 10 | from remount_union import remount_union 11 | from direct import direct_open_file, direct_fs_op 12 | 13 | def show_format(why): 14 | if why: 15 | print(why) 16 | print("Format:") 17 | print("\t", sys.argv[0], "<--no|--ov|--ovov>[=] [--fuse=] [--samefs|--maxfs=|--squashfs|--erofs] [--xdev] [--xino] [--meta] [--verify] [--ts=<0|1>] [-v] [+]") 18 | print("\t", sys.argv[0], "<--no|--ov|--ovov> [--fuse=] [--samefs|--squashfs|--erofs] [-s|--set-up]") 19 | print("\t", sys.argv[0], "[-c|--clean-up]") 20 | print("\t", sys.argv[0], "--open-file [-acdertvw] [-W ] [-R ] [-B] [-E ]") 21 | print("\t", sys.argv[0], "-- [*] [-aLlv] [-R ] [-B] [-E ]") 22 | sys.exit(2) 23 | 24 | cfg = config(sys.argv[0]) 25 | 26 | if len(sys.argv) < 2: 27 | show_format("Insufficient arguments") 28 | 29 | args = sys.argv[1:] 30 | 31 | ############################################################################### 32 | # 33 | # Handle requests to perform single probes 34 | # 35 | ############################################################################### 36 | if args[0] == "--open-file": 37 | try: 38 | direct_open_file(cfg, args[1:]) 39 | except ArgumentError as ae: 40 | show_format(str(ae)) 41 | except TestError as te: 42 | exit_error(str(te)) 43 | sys.exit(0) 44 | 45 | if (args[0] == "--chmod" or 46 | args[0] == "--link" or 47 | args[0] == "--mkdir" or 48 | args[0] == "--readlink" or 49 | args[0] == "--rename" or 50 | args[0] == "--rmdir" or 51 | args[0] == "--truncate" or 52 | args[0] == "--unlink" or 53 | args[0] == "--utimes"): 54 | try: 55 | direct_fs_op(cfg, args) 56 | sys.exit(0) 57 | except ArgumentError as ae: 58 | show_format(str(ae)) 59 | except TestError as te: 60 | exit_error(str(te)) 61 | sys.exit(0) 62 | 63 | ############################################################################### 64 | # 65 | # Unmount old attempts 66 | # 67 | ############################################################################### 68 | clean_up(cfg) 69 | 70 | if (args[0] == "-c" or args[0] == "--clean-up"): 71 | sys.exit(0) 72 | 73 | ############################################################################### 74 | # 75 | # Work out the test parameters 76 | # 77 | ############################################################################### 78 | recycle_list = [ "" ] 79 | maxlayers = 0 80 | if args[0] == "--no": 81 | cfg.set_testing_none() 82 | elif args[0].startswith("--ov"): 83 | cfg.set_testing_overlayfs() 84 | if args[0].startswith("--ovov"): 85 | cfg.set_nested() 86 | s = args[0] 87 | i = s.rfind("=") 88 | if i >= 0: 89 | n = s[i+1:] 90 | recycle_list = [ n, "" ] 91 | maxlayers = int(n) 92 | if maxlayers < 0: 93 | show_format("Invalid value for maxlayers >= 0") 94 | else: 95 | show_format("Invalid test type selector (--ov or --no)") 96 | args = args[1:] 97 | 98 | if len(args) > 0 and args[0].startswith("--fuse="): 99 | if not cfg.testing_overlayfs() or cfg.is_nested(): 100 | show_format("--fuse requires --ov") 101 | s = args[0] 102 | t = s[s.rfind("=")+1:] 103 | cfg.set_fusefs(t) 104 | args = args[1:] 105 | 106 | xino = None 107 | index_def = None 108 | index_opt = None 109 | metacopy = None 110 | redirect_dir = None 111 | if cfg.is_fusefs(): 112 | # fuse-overlayfs only supports redirect_dir=off 113 | # user can disable redirect_dir with --xdev 114 | redirect_dir = True 115 | elif cfg.testing_overlayfs(): 116 | # Overlayfs feature "redirect_dir" is auto enabled with kernel version >= v4.10, 117 | # unless explicitly disabled with --xdev or by mount option. When redirect_dir 118 | # is disabled, overlayfs tests skip rename tests that would result in EXDEV. 119 | if "redirect_dir=on" in cfg.mntopts(): 120 | redirect_dir_off = False 121 | else: 122 | # userxattr and any redirect= except for redirect=on disables directory rename 123 | redirect_dir_off = any(x in cfg.mntopts() for x in ["redirect_dir", "userxattr"]) 124 | if not redirect_dir_off: 125 | redirect_dir = check_bool_modparam("redirect_dir") 126 | # Overlayfs feature "index" can be enabled with --verify or by mount option on kernel version >= v4.13. 127 | # When index is disabled some verifications in multi layer tests may fail due to broken hardlinks. 128 | # When index is enabled we set_verify(), because all verifications are expected to pass. 129 | index_def = check_bool_modparam("index") 130 | if not index_def is None: 131 | index_opt = check_bool_mntopt("index", cfg.mntopts(), None, onopt2="nfs_export=on") 132 | if index_def or index_opt: 133 | cfg.set_verify() 134 | # Overlayfs feature "xino" can be enabled with --xino or by mount option on kernel version >= v4.17. 135 | # When xino is enabled we set_xino(), so st_ino/st_dev verifications will work correctly. 136 | xino_def = check_bool_modparam("xino_auto") 137 | if not xino_def is None: 138 | xino = check_bool_mntopt("xino", cfg.mntopts(), xino_def, onopt2="xino=auto") 139 | if xino: 140 | cfg.set_xino() 141 | # Overlayfs feature "metacopy" can be enabled with --meta and by mount option on kernel version >= v4.19. 142 | # When metacopy is enabled we set_metacopy(), so copy up verifications will work correctly. 143 | metacopy_def = check_bool_modparam("metacopy") 144 | if not metacopy_def is None: 145 | metacopy = check_bool_mntopt("metacopy", cfg.mntopts(), metacopy_def, offopt2="nfs_export=on") 146 | if metacopy: 147 | cfg.set_metacopy() 148 | 149 | maxfs = cfg.maxfs() 150 | if len(args) > 0 and (args[0] == "--samefs" or args[0] == "--squashfs" or args[0] == "--erofs" or args[0].startswith("--maxfs=")): 151 | if args[0] == "--samefs": 152 | # maxfs < 0 means samefs 153 | maxfs = -1 154 | if cfg.env_lower_mntroot(): 155 | show_format("--samefs is incompatible with UNIONMOUNT_LOWERDIR environment variable") 156 | elif args[0] == "--squashfs": 157 | # maxfs 0 means one upper fs and one lower fs 158 | maxfs = 0 159 | cfg.set_squashfs() 160 | elif args[0] == "--erofs": 161 | # maxfs 0 means one upper fs and one lower fs 162 | maxfs = 0 163 | cfg.set_erofs() 164 | elif args[0].startswith("--maxfs="): 165 | s = args[0] 166 | n = s[s.rfind("=")+1:] 167 | maxfs = int(n) 168 | if maxfs < 0: 169 | show_format("Invalid value for maxfs >= 0") 170 | args = args[1:] 171 | cfg.set_maxfs(maxfs) 172 | 173 | # We might be being asked to just set up and then leave without doing 174 | # any further testing. 175 | if len(args) > 0 and ( args[0] == "-s" or args[0] == "--set-up" ): 176 | if len(args) > 1: 177 | show_format("Too many arguments for --set-up") 178 | ctx = test_context(cfg) 179 | set_up(ctx) 180 | mount_union(ctx) 181 | sys.exit(0) 182 | 183 | termslash = "0" 184 | while len(args) > 0 and args[0].startswith("-"): 185 | if args[0] == "-v": 186 | cfg.set_verbose() 187 | elif args[0] == "--ts=0": 188 | termslash = "0" 189 | elif args[0] == "--ts=1": 190 | termslash = "1" 191 | elif args[0] == "--xdev": 192 | # Disable auto-enable of "redirect_dir" and skip dir rename tests 193 | redirect_dir = None 194 | elif args[0] == "--xino": 195 | if xino is None: 196 | print("xino not supported - ignoring --xino") 197 | else: 198 | xino = True 199 | cfg.set_xino() 200 | elif args[0] == "--meta": 201 | if metacopy is None: 202 | print("metacopy not supported - ignoring --meta") 203 | else: 204 | cfg.add_mntopt("metacopy=on") 205 | cfg.set_metacopy() 206 | elif args[0] == "--verify": 207 | cfg.set_verify() 208 | # auto enable index for --verify unless explicitly disabled 209 | if index_def is False and not index_opt is False: 210 | cfg.add_mntopt("index=on") 211 | else: 212 | show_format("Invalid flag " + args[0]) 213 | args = args[1:] 214 | 215 | # Auto-enable redired_dir unless explicitly disabled by --xdev or mount options 216 | if redirect_dir is False: 217 | cfg.add_mntopt("redirect_dir=on") 218 | redirect_dir = True 219 | 220 | # Auto-upgrade xino=auto to xino=on for kernel < v5.7 221 | if xino: 222 | cfg.add_mntopt("xino=on") 223 | 224 | ############################################################################### 225 | # 226 | # Work out the list of tests to run 227 | # 228 | ############################################################################### 229 | tests = [ 230 | "open-plain", 231 | "open-trunc", 232 | "open-creat", 233 | "open-creat-trunc", 234 | "open-creat-excl", 235 | "open-creat-excl-trunc", 236 | "noent-plain", 237 | "noent-trunc", 238 | "noent-creat", 239 | "noent-creat-trunc", 240 | "noent-creat-excl", 241 | "noent-creat-excl-trunc", 242 | "sym1-plain", 243 | "sym1-trunc", 244 | "sym1-creat", 245 | "sym1-creat-excl", 246 | "sym2-plain", 247 | "sym2-trunc", 248 | "sym2-creat", 249 | "sym2-creat-excl", 250 | "symx-plain", 251 | "symx-trunc", 252 | "symx-creat", 253 | "symx-creat-excl", 254 | "symx-creat-trunc", 255 | "truncate", 256 | "dir-open", 257 | "dir-weird-open", 258 | "dir-open-dir", 259 | "dir-sym1-open", 260 | "dir-sym1-weird-open", 261 | "dir-sym2-open", 262 | "dir-sym2-weird-open", 263 | "readlink", 264 | "mkdir", 265 | "rmdir", 266 | "rmtree", 267 | "rmtree-new", 268 | "hard-link", 269 | "hard-link-dir", 270 | "hard-link-sym", 271 | "unlink", 272 | "rename-file", 273 | "rename-hard-link", 274 | "rename-new-dir", 275 | "rename-new-pop-dir", 276 | "rename-mass", 277 | "rename-mass-2", 278 | "rename-mass-3", 279 | "rename-mass-4", 280 | "rename-mass-5", 281 | "rename-mass-dir", 282 | "rename-mass-sym", 283 | "impermissible" 284 | ] 285 | 286 | # For backward compat with kernel version < v4.10 or with flag --xdev, 287 | # run an alternative test to verify EXDEV behavior. Otherwise, run all 288 | # directory rename tests. 289 | if cfg.testing_overlayfs() and not redirect_dir: 290 | tests += [ 291 | "rename-exdev", 292 | ] 293 | else: 294 | tests += [ 295 | "rename-dir", 296 | "rename-empty-dir", 297 | "rename-pop-dir", 298 | "rename-move-dir", 299 | ] 300 | 301 | if len(args) > 0: 302 | tests = args 303 | 304 | if cfg.testing_overlayfs(): 305 | if cfg.is_nested(): 306 | test_what = "--ovov" 307 | else: 308 | test_what = "--ov" 309 | else: 310 | test_what = "--no" 311 | 312 | for test in tests: 313 | for recycle in recycle_list: 314 | test_how = test_what 315 | if recycle != "": 316 | test_how = test_what + "=" + str(maxlayers) 317 | if cfg.testing_overlayfs(): 318 | if maxfs > 0: 319 | test_how += " --maxfs=" + str(maxfs) 320 | elif maxfs < 0: 321 | test_how += " --samefs" 322 | if not redirect_dir: 323 | test_how += " --xdev" 324 | if cfg.is_xino(): 325 | test_how += " --xino" 326 | if cfg.is_metacopy(): 327 | test_how += " --meta" 328 | if cfg.is_verify(): 329 | test_how += " --verify" 330 | msg = cfg.progname() + " " + test_how + " " + test 331 | print("***"); 332 | print("***", msg); 333 | print("***"); 334 | if cfg.is_verbose(): 335 | write_kmsg(msg); 336 | 337 | ctx = test_context(cfg, termslash == "1", False, recycle != "", maxlayers) 338 | 339 | # Construct the union 340 | set_up(ctx) 341 | mount_union(ctx) 342 | os.sync() 343 | 344 | # Run a test script 345 | script = __import__("tests." + test, globals(), locals(), ['subtests']) 346 | try: 347 | subtests = [] 348 | for name in dir(script): 349 | if not name.startswith("subtest_"): 350 | continue 351 | subtest = getattr(script, name) 352 | if type(subtest) != types.FunctionType: 353 | continue 354 | subtests.append((inspect.getfile(subtest), 355 | inspect.getsourcelines(subtest)[1], 356 | subtest.__doc__, 357 | subtest)) 358 | 359 | # Perform the subtests in the order they're defined in the file 360 | for (f, line, doc, func) in sorted(subtests, key=lambda s: s[1]): 361 | ctx.begin_test(f, line, doc) 362 | func(ctx) 363 | 364 | except TestError as te: 365 | exit_error(str(te)) 366 | 367 | # Stop if the kernel is now tainted 368 | check_not_tainted() 369 | 370 | # Make sure that all dentries and inodes are correctly released 371 | unmount_union(ctx) 372 | del ctx 373 | 374 | # Leave the union mounted for further playing 375 | ctx = test_context(cfg) 376 | set_up(ctx) 377 | mount_union(ctx) 378 | -------------------------------------------------------------------------------- /set_up.py: -------------------------------------------------------------------------------- 1 | # 2 | # Create and set up a lower layer for the test scripts to use 3 | # 4 | from tool_box import * 5 | import os, shutil 6 | 7 | def create_file(name, content): 8 | fd = open(name, "w") 9 | fd.write(content) 10 | fd.close() 11 | 12 | # Cleanup old test mounts regardless of the current test setup, because old 13 | # test may have used a different setup (e.g. samefs vs. non-samefs). 14 | def clean_up(cfg): 15 | base_mntroot = cfg.base_mntroot() 16 | lower_mntroot = cfg.old_lower_mntroot() 17 | upper_mntroot = cfg.old_upper_mntroot() 18 | union_mntroot = cfg.old_union_mntroot() 19 | 20 | os.sync() 21 | 22 | try: 23 | while system("grep -q ' " + union_mntroot + " ' /proc/mounts" + 24 | " && umount " + union_mntroot): 25 | pass 26 | except RuntimeError: 27 | pass 28 | 29 | try: 30 | while system("grep -q 'lower_layer " + lower_mntroot + " ' /proc/mounts" + 31 | " && umount " + lower_mntroot): 32 | pass 33 | except RuntimeError: 34 | pass 35 | 36 | try: 37 | # Cleanup middle/upper/nested layers from [--ov|--ovov] --maxfs=M setup 38 | while system("grep -q '_layer " + upper_mntroot + "/.[0-9]* ' /proc/mounts" + 39 | " && umount " + upper_mntroot + "/* 2>/dev/null"): 40 | pass 41 | except RuntimeError: 42 | pass 43 | 44 | try: 45 | while system("grep -q '_layer " + upper_mntroot + " ' /proc/mounts" + 46 | " && umount " + upper_mntroot): 47 | pass 48 | except RuntimeError: 49 | pass 50 | 51 | try: 52 | # Cleanup middle/upper/nested layers and overlay mount from setup with basedir 53 | while system("grep -q ' " + base_mntroot + "/.[0-9]* ' /proc/mounts" + 54 | " && umount " + base_mntroot + "/* 2>/dev/null"): 55 | pass 56 | except RuntimeError: 57 | pass 58 | 59 | try: 60 | # Cleanup basefs mount from --ov --samefs setup 61 | while system("grep -q 'lower_layer " + base_mntroot + " ' /proc/mounts" + 62 | " && umount " + base_mntroot): 63 | pass 64 | except RuntimeError: 65 | pass 66 | 67 | def set_up(ctx): 68 | cfg = ctx.config() 69 | base_mntroot = cfg.base_mntroot() 70 | lower_mntroot = cfg.lower_mntroot() 71 | union_mntroot = cfg.union_mntroot() 72 | lowerdir = cfg.lowerdir() 73 | lowerimg = cfg.lowerimg() 74 | testdir = cfg.testdir() 75 | 76 | if cfg.should_mount_base(): 77 | # Create base fs for all layers and union mount point 78 | system("mount " + base_mntroot + " 2>/dev/null" 79 | " || mount -t tmpfs lower_layer " + base_mntroot) 80 | system("mount --make-private " + base_mntroot) 81 | 82 | if cfg.should_use_base(): 83 | try: 84 | if lower_mntroot.startswith(base_mntroot): 85 | os.mkdir(lower_mntroot) 86 | if union_mntroot.startswith(base_mntroot): 87 | os.mkdir(union_mntroot) 88 | except OSError: 89 | # Cleanup leftover layers from previous run in case base fs is not tmpfs 90 | if base_mntroot: 91 | system("rm -rf " + base_mntroot + "/*") 92 | if lower_mntroot.startswith(base_mntroot): 93 | os.mkdir(lower_mntroot) 94 | if union_mntroot.startswith(base_mntroot): 95 | os.mkdir(union_mntroot) 96 | 97 | if cfg.should_mount_lower(): 98 | # Create a lower layer to union over 99 | system("mount " + lower_mntroot + " 2>/dev/null" 100 | " || mount -t tmpfs lower_layer " + lower_mntroot) 101 | system("mount --make-private " + lower_mntroot) 102 | 103 | # 104 | # Create a few test files we can use in the lower layer 105 | # 106 | try: 107 | os.mkdir(lowerdir) 108 | except OSError: 109 | system("rm -rf " + lowerdir) 110 | os.mkdir(lowerdir) 111 | 112 | pieces = testdir.split("/") 113 | del pieces[0] 114 | path = "" 115 | for i in pieces: 116 | path += "/" + i 117 | ctx.record_file(path, "d") 118 | ctx.set_cwd(testdir) 119 | 120 | for i in range(100, 130): 121 | si = str(i) 122 | 123 | # Under the test directory, we create a bunch of regular files 124 | # containing data called foo100 to foo129: 125 | create_file(lowerdir + "/foo" + si, ":xxx:yyy:zzz") 126 | rec = ctx.record_file("foo" + si, "r") 127 | 128 | # Then we create a bunch of direct symlinks to those files 129 | to = "../a/foo" + si 130 | os.symlink(to, lowerdir + "/direct_sym" + si) 131 | rec = ctx.record_file("direct_sym" + si, "s", to, rec) 132 | 133 | # Then we create a bunch of indirect symlinks to those files 134 | to = "direct_sym" + si 135 | os.symlink(to, lowerdir + "/indirect_sym" + si) 136 | ctx.record_file("indirect_sym" + si, "s", to, rec) 137 | 138 | # Then we create a bunch symlinks that don't point to extant files 139 | to = "no_foo" + si 140 | os.symlink(to, lowerdir + "/pointless" + si) 141 | rec = ctx.record_file("no_foo" + si, None) 142 | ctx.record_file("pointless" + si, "s", to, rec) 143 | 144 | # We create a bunch of directories, each with an empty file 145 | # and a populated subdir 146 | os.mkdir(lowerdir + "/dir" + si) 147 | rec = ctx.record_file("dir" + si, "d") 148 | create_file(lowerdir + "/dir" + si + "/a", "") 149 | ctx.record_file("dir" + si + "/a", "f") 150 | 151 | os.mkdir(lowerdir + "/dir" + si + "/pop") 152 | ctx.record_file("dir" + si + "/pop", "d") 153 | create_file(lowerdir + "/dir" + si + "/pop/b", ":aaa:bbb:ccc") 154 | ctx.record_file("dir" + si + "/pop/b", "f") 155 | os.mkdir(lowerdir + "/dir" + si + "/pop/c") 156 | ctx.record_file("dir" + si + "/pop/c", "d") 157 | 158 | # And add direct and indirect symlinks to those 159 | to = "../a/dir" + si 160 | os.symlink(to, lowerdir + "/direct_dir_sym" + si) 161 | rec = ctx.record_file("direct_dir_sym" + si, "s", to, rec) 162 | #ctx.record_file("direct_dir_sym" + si + "/a", "f") 163 | 164 | to = "direct_dir_sym" + si 165 | os.symlink(to, lowerdir + "/indirect_dir_sym" + si) 166 | ctx.record_file("indirect_dir_sym" + si, "s", to, rec) 167 | #ctx.record_file("indirect_dir_sym" + si + "/a", "f") 168 | 169 | # And a bunch of empty directories 170 | os.mkdir(lowerdir + "/empty" + si) 171 | ctx.record_file("empty" + si, "d") 172 | 173 | # Everything above is then owned by the bin user 174 | for f in [ "foo", "direct_sym", "indirect_sym", "pointless" ]: 175 | os.lchown(lowerdir + "/" + f + si, 1, 1) 176 | 177 | # Create some root-owned regular files also 178 | create_file(lowerdir + "/rootfile" + si, ":xxx:yyy:zzz") 179 | ctx.record_file("rootfile" + si, "r") 180 | 181 | # Non-existent dir 182 | ctx.record_file("no_dir" + si, None) 183 | 184 | if cfg.is_squashfs(): 185 | system("mksquashfs " + lowerdir + " " + lowerimg + " -keep-as-directory > /dev/null"); 186 | system("mount -o loop,ro " + lowerimg + " " + lower_mntroot) 187 | system("mount --make-private " + lower_mntroot) 188 | if cfg.is_erofs(): 189 | import tempfile 190 | with tempfile.TemporaryDirectory() as tmpdirname: 191 | system("cp -fR " + lowerdir + " " + tmpdirname) 192 | system("mkfs.erofs " + lowerimg + " " + tmpdirname + " > /dev/null"); 193 | system("mount -t erofs -o loop,ro " + lowerimg + " " + lower_mntroot) 194 | system("mount --make-private " + lower_mntroot) 195 | elif cfg.should_mount_lower_ro(): 196 | # Make overlay lower layer read-only 197 | system("mount -o remount,ro " + lower_mntroot) 198 | ctx.note_lower_fs(lowerdir) 199 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Class of object containing current test configuration 3 | # 4 | 5 | __copyright__ = """ 6 | Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. 7 | Written by David Howells (dhowells@redhat.com) 8 | 9 | This program is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU General Public Licence version 2 as 11 | published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public Licence for more details. 17 | 18 | You should have received a copy of the GNU General Public Licence 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | """ 22 | 23 | import os 24 | 25 | class config: 26 | def __init__(self, progname): 27 | self.__progname = progname 28 | self.__testing_overlayfs = False 29 | self.__testing_none = False 30 | self.__base_mntroot = os.getenv('UNIONMOUNT_BASEDIR') 31 | self.__lower_mntroot = os.getenv('UNIONMOUNT_LOWERDIR') 32 | self.__union_mntroot = os.getenv('UNIONMOUNT_MNTPOINT') 33 | self.__mntopts = os.getenv('UNIONMOUNT_MNTOPTIONS') 34 | print("Environment variables:") 35 | if self.__base_mntroot: 36 | print("UNIONMOUNT_BASEDIR='" + self.__base_mntroot + "'") 37 | if self.__lower_mntroot: 38 | print("UNIONMOUNT_LOWERDIR='" + self.__lower_mntroot + "'") 39 | if self.__union_mntroot: 40 | print("UNIONMOUNT_MNTPOINT='" + self.__union_mntroot + "'") 41 | if self.__mntopts: 42 | print("UNIONMOUNT_MNTOPTIONS='" + self.__mntopts + "'") 43 | # Allow user provided options with or without -o 44 | if not self.__mntopts.startswith("-o"): 45 | self.__mntopts = "-o" + self.__mntopts 46 | else: # Use arbitrary non empty options to simplify add_mntopt() 47 | self.__mntopts = "-orw" 48 | print() 49 | if self.__base_mntroot and not self.__lower_mntroot: 50 | # Empty UNIONMOUNT_LOWERDIR with non-empty UNIONMOUNT_BASEDIR imply --samefs 51 | # unless user requests maxfs= 52 | self.__maxfs = -1 53 | else: 54 | self.__maxfs = 0 55 | self.__verbose = False 56 | self.__verify = False 57 | self.__squashfs = False 58 | self.__erofs = False 59 | self.__metacopy = False 60 | self.__nested = False 61 | self.__xino = False 62 | self.__fusefs = False 63 | self.__fstype = "overlay" 64 | self.__fsname = "overlay" 65 | 66 | def progname(self): 67 | return self.__progname 68 | 69 | def testing_none(self): 70 | return self.__testing_none 71 | def testing_overlayfs(self): 72 | return self.__testing_overlayfs 73 | 74 | def set_testing_none(self): 75 | self.__testing_none = True 76 | 77 | def set_testing_overlayfs(self): 78 | self.__testing_overlayfs = True 79 | 80 | # base dir is used only for --ov --samefs, in which case: 81 | # BASEDIR/l is lowermost layer 82 | # BASEDIR/0/u is the first layer above it, which starts as upper layer 83 | # and may later be rotated to lower layers. 84 | # BASEDIR/m is the union mount point. 85 | # user provided UNIONMOUNT_BASEDIR should already be mounted. 86 | def should_use_base(self): 87 | return self.__base_mntroot or (self.testing_overlayfs() and self.is_samefs()) 88 | def should_mount_base(self): 89 | return not self.__base_mntroot and self.should_use_base() 90 | def base_mntroot(self): 91 | return self.__base_mntroot or "/base" 92 | def env_base_mntroot(self): 93 | return self.__base_mntroot 94 | # lower dir is mounted ro for --ov (without --samefs) ... 95 | def should_mount_lower_ro(self): 96 | return self.testing_overlayfs() and not self.is_samefs() and not self.__lower_mntroot 97 | # ... and mounted rw for --no 98 | # user provided UNIONMOUNT_LOWERDIR should already be mounted. 99 | def should_mount_lower_rw(self): 100 | return self.testing_none() and not self.__lower_mntroot 101 | def should_mount_lower(self): 102 | return self.should_mount_lower_ro() or self.should_mount_lower_rw() 103 | # lowermost layer is either at UNIONMOUNT_LOWERDIR, /lower or BASEDIR/l 104 | def lower_mntroot(self): 105 | if self.__lower_mntroot: 106 | return self.__lower_mntroot 107 | if self.should_use_base(): 108 | return self.base_mntroot() + "/l" 109 | return self.old_lower_mntroot() 110 | def old_lower_mntroot(self): 111 | return self.__lower_mntroot or "/lower" 112 | def env_lower_mntroot(self): 113 | return self.__lower_mntroot 114 | # upper dir is mounted for --ov (without --samefs) 115 | def should_mount_upper(self): 116 | return self.testing_overlayfs() and not self.is_samefs() and not self.__base_mntroot 117 | # layers (0..N) above lowermost are either at /upper/N or at BASEDIR/N 118 | def upper_mntroot(self): 119 | if self.should_use_base(): 120 | return self.base_mntroot() 121 | return self.old_upper_mntroot() 122 | def old_upper_mntroot(self): 123 | return self.__base_mntroot or "/upper" 124 | # union mount point is either at /mnt or at BASEDIR/m 125 | def union_mntroot(self): 126 | if self.__union_mntroot: 127 | return self.__union_mntroot 128 | if self.should_use_base(): 129 | return self.base_mntroot() + "/m" 130 | return self.old_union_mntroot() 131 | def old_union_mntroot(self): 132 | return self.__union_mntroot or "/mnt" 133 | def env_union_mntroot(self): 134 | return self.__union_mntroot 135 | def lowerdir(self): 136 | return self.lower_mntroot() + "/a" 137 | def lowerimg(self): 138 | return self.lower_mntroot() + "/a.img" 139 | def testdir(self): 140 | return self.union_mntroot() + "/a" 141 | 142 | def set_verbose(self, to=True): 143 | self.__verbose = to 144 | def is_verbose(self): 145 | return self.__verbose 146 | def set_verify(self, to=True): 147 | self.__verify = to 148 | def is_verify(self): 149 | return self.__verify 150 | def set_maxfs(self, to): 151 | self.__maxfs = to 152 | def maxfs(self): 153 | return self.__maxfs 154 | def is_samefs(self): 155 | return self.__maxfs < 0 156 | def set_squashfs(self, to=True): 157 | self.__squashfs = to 158 | def is_squashfs(self): 159 | return self.__squashfs 160 | def set_erofs(self, to=True): 161 | self.__erofs = to 162 | def is_erofs(self): 163 | return self.__erofs 164 | def set_xino(self, to=True): 165 | self.__xino = to 166 | def is_xino(self): 167 | return self.__xino 168 | def set_metacopy(self, to=True): 169 | self.__metacopy = to 170 | def is_metacopy(self): 171 | return self.__metacopy 172 | def set_nested(self, to=True): 173 | self.__nested = to 174 | def is_nested(self): 175 | return self.__nested 176 | 177 | def add_mntopt(self, opt): 178 | self.__mntopts += "," + opt 179 | def set_mntopts(self, opts): 180 | self.__mntopts = opts 181 | def mntopts(self): 182 | return self.__mntopts 183 | 184 | def fsname(self): 185 | return self.__fsname 186 | def fstype(self): 187 | return self.__fstype 188 | def set_fusefs(self, to): 189 | self.__fusefs = True 190 | self.__fsname = to 191 | self.__fstype = "fuse." + to 192 | def is_fusefs(self): 193 | return self.__fusefs 194 | -------------------------------------------------------------------------------- /tests/dir-open-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing directory; O_DIRECTORY 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_DIRECTORY | O_RDONLY""" 12 | f = ctx.non_empty_dir() + ctx.termslash() 13 | 14 | ctx.open_dir(f, ro=1) 15 | ctx.open_dir(f, ro=1) 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_DIRECTORY | O_WRONLY""" 20 | f = ctx.non_empty_dir() + ctx.termslash() 21 | 22 | ctx.open_dir(f, wo=1, err=EISDIR) 23 | ctx.open_dir(f, ro=1) 24 | ctx.open_dir(f, wo=1, err=EISDIR) 25 | ctx.open_dir(f, ro=1) 26 | 27 | # Open write-only and overwrite twice 28 | def subtest_3(ctx): 29 | """Open O_DIRECTORY | O_WRONLY * 2""" 30 | f = ctx.non_empty_dir() + ctx.termslash() 31 | 32 | ctx.open_dir(f, wo=1, err=EISDIR) 33 | ctx.open_dir(f, wo=1, err=EISDIR) 34 | ctx.open_dir(f, ro=1) 35 | 36 | # Open write-only and append 37 | def subtest_4(ctx): 38 | """Open O_DIRECTORY | O_APPEND|O_WRONLY""" 39 | f = ctx.non_empty_dir() + ctx.termslash() 40 | 41 | ctx.open_dir(f, app=1, err=EISDIR) 42 | ctx.open_dir(f, ro=1) 43 | ctx.open_dir(f, app=1, err=EISDIR) 44 | ctx.open_dir(f, ro=1) 45 | 46 | # Open read/write and overwrite 47 | def subtest_5(ctx): 48 | """Open O_DIRECTORY | O_RDWR""" 49 | f = ctx.non_empty_dir() + ctx.termslash() 50 | 51 | ctx.open_dir(f, rw=1, err=EISDIR) 52 | ctx.open_dir(f, ro=1) 53 | ctx.open_dir(f, rw=1, err=EISDIR) 54 | ctx.open_dir(f, ro=1) 55 | 56 | # Open read/write and append 57 | def subtest_6(ctx): 58 | """Open O_DIRECTORY | O_APPEND|O_RDWR""" 59 | f = ctx.non_empty_dir() + ctx.termslash() 60 | 61 | ctx.open_dir(f, ro=1, app=1, err=EISDIR) 62 | ctx.open_dir(f, ro=1) 63 | ctx.open_dir(f, ro=1, app=1, err=EISDIR) 64 | ctx.open_dir(f, ro=1) 65 | -------------------------------------------------------------------------------- /tests/dir-open.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing directory; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_RDONLY""" 12 | f = ctx.non_empty_dir() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1) 15 | ctx.open_file(f, ro=1) 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_WRONLY""" 20 | f = ctx.non_empty_dir() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, err=EISDIR) 23 | ctx.open_file(f, ro=1) 24 | ctx.open_file(f, wo=1, err=EISDIR) 25 | ctx.open_file(f, ro=1) 26 | 27 | # Open write-only and overwrite twice 28 | def subtest_3(ctx): 29 | """Open O_WRONLY * 2""" 30 | f = ctx.non_empty_dir() + ctx.termslash() 31 | 32 | ctx.open_file(f, wo=1, err=EISDIR) 33 | ctx.open_file(f, wo=1, err=EISDIR) 34 | ctx.open_file(f, ro=1) 35 | 36 | # Open write-only and append 37 | def subtest_4(ctx): 38 | """Open O_APPEND|O_WRONLY""" 39 | f = ctx.non_empty_dir() + ctx.termslash() 40 | 41 | ctx.open_file(f, app=1, err=EISDIR) 42 | ctx.open_file(f, ro=1) 43 | ctx.open_file(f, app=1, err=EISDIR) 44 | ctx.open_file(f, ro=1) 45 | 46 | # Open read/write and overwrite 47 | def subtest_5(ctx): 48 | """Open O_RDWR""" 49 | f = ctx.non_empty_dir() + ctx.termslash() 50 | 51 | ctx.open_file(f, rw=1, err=EISDIR) 52 | ctx.open_file(f, ro=1) 53 | ctx.open_file(f, rw=1, err=EISDIR) 54 | ctx.open_file(f, ro=1) 55 | 56 | # Open read/write and append 57 | def subtest_6(ctx): 58 | """Open O_APPEND|O_RDWR""" 59 | f = ctx.non_empty_dir() + ctx.termslash() 60 | 61 | ctx.open_file(f, ro=1, app=1, err=EISDIR) 62 | ctx.open_file(f, ro=1) 63 | ctx.open_file(f, ro=1, app=1, err=EISDIR) 64 | ctx.open_file(f, ro=1) 65 | -------------------------------------------------------------------------------- /tests/dir-sym1-open.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through direct symlink of existing directory; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open(dir symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(dir symlink) O_RDONLY""" 12 | symlink = ctx.direct_dir_sym() + ctx.termslash() 13 | f = ctx.non_empty_dir() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1) 16 | ctx.open_file(symlink, ro=1) 17 | 18 | # Open(dir symlink) write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(dir symlink) O_WRONLY""" 21 | symlink = ctx.direct_dir_sym() + ctx.termslash() 22 | f = ctx.non_empty_dir() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, err=EISDIR) 25 | ctx.open_file(symlink, ro=1) 26 | ctx.open_file(symlink, wo=1, err=EISDIR) 27 | ctx.open_file(symlink, ro=1) 28 | 29 | # Open(dir symlink) write-only and append 30 | def subtest_3(ctx): 31 | """Open(dir symlink) O_APPEND|O_WRONLY""" 32 | symlink = ctx.direct_dir_sym() + ctx.termslash() 33 | f = ctx.non_empty_dir() + ctx.termslash() 34 | 35 | ctx.open_file(symlink, app=1, err=EISDIR) 36 | ctx.open_file(symlink, ro=1) 37 | ctx.open_file(symlink, app=1, err=EISDIR) 38 | ctx.open_file(symlink, ro=1) 39 | 40 | # Open(dir symlink) read/write and overwrite 41 | def subtest_4(ctx): 42 | """Open(dir symlink) O_RDWR""" 43 | symlink = ctx.direct_dir_sym() + ctx.termslash() 44 | f = ctx.non_empty_dir() + ctx.termslash() 45 | 46 | ctx.open_file(symlink, rw=1, err=EISDIR) 47 | ctx.open_file(symlink, ro=1) 48 | ctx.open_file(symlink, rw=1, err=EISDIR) 49 | ctx.open_file(symlink, ro=1) 50 | 51 | # Open(dir symlink) read/write and append 52 | def subtest_5(ctx): 53 | """Open(dir symlink) O_APPEND|O_RDWR""" 54 | symlink = ctx.direct_dir_sym() + ctx.termslash() 55 | f = ctx.non_empty_dir() + ctx.termslash() 56 | 57 | ctx.open_file(symlink, ro=1, app=1, err=EISDIR) 58 | ctx.open_file(symlink, ro=1) 59 | ctx.open_file(symlink, ro=1, app=1, err=EISDIR) 60 | ctx.open_file(symlink, ro=1) 61 | -------------------------------------------------------------------------------- /tests/dir-sym1-weird-open.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through direct symlink of existing directory; with create, exclusive and 6 | # truncate 7 | # 8 | ############################################################################### 9 | 10 | # Open(dir symlink) read-only and create 11 | def subtest_1(ctx): 12 | """Open(dir symlink) O_RDONLY | O_CREAT""" 13 | symlink = ctx.direct_dir_sym() + ctx.termslash() 14 | f = ctx.non_empty_dir() + ctx.termslash() 15 | 16 | ctx.open_file(symlink, ro=1, crt=1, err=EISDIR) 17 | ctx.open_file(symlink, ro=1) 18 | 19 | # Open(dir symlink) read-only and create exclusive 20 | def subtest_2(ctx): 21 | """Open(dir symlink) O_RDONLY | O_CREAT | O_EXCL""" 22 | symlink = ctx.direct_dir_sym() + ctx.termslash() 23 | f = ctx.non_empty_dir() + ctx.termslash() 24 | 25 | ctx.open_file(symlink, ro=1, crt=1, ex=1, err=EEXIST) 26 | ctx.open_file(symlink, ro=1) 27 | 28 | # Open(dir symlink) read-only and truncate 29 | def subtest_3(ctx): 30 | """Open(dir symlink) O_RDONLY | O_TRUNC""" 31 | symlink = ctx.direct_dir_sym() + ctx.termslash() 32 | f = ctx.non_empty_dir() + ctx.termslash() 33 | 34 | ctx.open_file(symlink, ro=1, tr=1, err=EISDIR) 35 | ctx.open_file(symlink, ro=1) 36 | 37 | # Open(dir symlink) read-only and truncate create 38 | def subtest_4(ctx): 39 | """Open(dir symlink) O_RDONLY | O_TRUNC | O_CREAT""" 40 | symlink = ctx.direct_dir_sym() + ctx.termslash() 41 | f = ctx.non_empty_dir() + ctx.termslash() 42 | 43 | ctx.open_file(symlink, ro=1, tr=1, crt=1, err=EISDIR) 44 | ctx.open_file(symlink, ro=1) 45 | 46 | # Open(dir symlink) read-only and truncate create exclusive 47 | def subtest_5(ctx): 48 | """Open(dir symlink) O_RDONLY | O_TRUNC | O_CREAT | O_EXCL""" 49 | symlink = ctx.direct_dir_sym() + ctx.termslash() 50 | f = ctx.non_empty_dir() + ctx.termslash() 51 | 52 | ctx.open_file(symlink, ro=1, tr=1, crt=1, ex=1, err=EEXIST) 53 | ctx.open_file(symlink, ro=1) 54 | 55 | # Open(dir symlink) write-only and create 56 | def subtest_6(ctx): 57 | """Open(dir symlink) O_WRONLY | O_CREAT""" 58 | symlink = ctx.direct_dir_sym() + ctx.termslash() 59 | f = ctx.non_empty_dir() + ctx.termslash() 60 | 61 | ctx.open_file(symlink, wo=1, crt=1, err=EISDIR) 62 | ctx.open_file(symlink, ro=1) 63 | 64 | # Open(dir symlink) write-only and create exclusive 65 | def subtest_7(ctx): 66 | """Open(dir symlink) O_WRONLY | O_CREAT | O_EXCL""" 67 | symlink = ctx.direct_dir_sym() + ctx.termslash() 68 | f = ctx.non_empty_dir() + ctx.termslash() 69 | 70 | ctx.open_file(symlink, wo=1, crt=1, ex=1, err=EEXIST) 71 | ctx.open_file(symlink, ro=1) 72 | 73 | # Open(dir symlink) write-only and truncate 74 | def subtest_8(ctx): 75 | """Open(dir symlink) O_WRONLY | O_TRUNC""" 76 | symlink = ctx.direct_dir_sym() + ctx.termslash() 77 | f = ctx.non_empty_dir() + ctx.termslash() 78 | 79 | ctx.open_file(symlink, wo=1, tr=1, err=EISDIR) 80 | ctx.open_file(symlink, ro=1) 81 | 82 | # Open(dir symlink) write-only and truncate create 83 | def subtest_9(ctx): 84 | """Open(dir symlink) O_WRONLY | O_TRUNC | O_CREAT""" 85 | symlink = ctx.direct_dir_sym() + ctx.termslash() 86 | f = ctx.non_empty_dir() + ctx.termslash() 87 | 88 | ctx.open_file(symlink, wo=1, tr=1, crt=1, err=EISDIR) 89 | ctx.open_file(symlink, ro=1) 90 | 91 | # Open(dir symlink) write-only and truncate create exclusive 92 | def subtest_10(ctx): 93 | """Open(dir symlink) O_WRONLY | O_TRUNC | O_CREAT | O_EXCL""" 94 | symlink = ctx.direct_dir_sym() + ctx.termslash() 95 | f = ctx.non_empty_dir() + ctx.termslash() 96 | 97 | ctx.open_file(symlink, wo=1, tr=1, crt=1, ex=1, err=EEXIST) 98 | ctx.open_file(symlink, ro=1) 99 | -------------------------------------------------------------------------------- /tests/dir-sym2-open.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through indirect symlink of existing directory; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open(dir symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(dir symlink) O_RDONLY""" 12 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 13 | direct = ctx.direct_dir_sym() + ctx.termslash() 14 | f = ctx.non_empty_dir() + ctx.termslash() 15 | 16 | ctx.open_file(indirect, ro=1) 17 | ctx.open_file(indirect, ro=1) 18 | 19 | # Open(dir symlink) write-only and overwrite 20 | def subtest_2(ctx): 21 | """Open(dir symlink) O_WRONLY""" 22 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 23 | direct = ctx.direct_dir_sym() + ctx.termslash() 24 | f = ctx.non_empty_dir() + ctx.termslash() 25 | 26 | ctx.open_file(indirect, wo=1, err=EISDIR) 27 | ctx.open_file(indirect, ro=1) 28 | ctx.open_file(indirect, wo=1, err=EISDIR) 29 | ctx.open_file(indirect, ro=1) 30 | 31 | # Open(dir symlink) write-only and append 32 | def subtest_3(ctx): 33 | """Open(dir symlink) O_APPEND|O_WRONLY""" 34 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 35 | direct = ctx.direct_dir_sym() + ctx.termslash() 36 | f = ctx.non_empty_dir() + ctx.termslash() 37 | 38 | ctx.open_file(indirect, app=1, err=EISDIR) 39 | ctx.open_file(indirect, ro=1) 40 | ctx.open_file(indirect, app=1, err=EISDIR) 41 | ctx.open_file(indirect, ro=1) 42 | 43 | # Open(dir symlink) read/write and overwrite 44 | def subtest_4(ctx): 45 | """Open(dir symlink) O_RDWR""" 46 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 47 | direct = ctx.direct_dir_sym() + ctx.termslash() 48 | f = ctx.non_empty_dir() + ctx.termslash() 49 | 50 | ctx.open_file(indirect, rw=1, err=EISDIR) 51 | ctx.open_file(indirect, ro=1) 52 | ctx.open_file(indirect, rw=1, err=EISDIR) 53 | ctx.open_file(indirect, ro=1) 54 | 55 | # Open(dir symlink) read/write and append 56 | def subtest_5(ctx): 57 | """Open(dir symlink) O_APPEND|O_RDWR""" 58 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 59 | direct = ctx.direct_dir_sym() + ctx.termslash() 60 | f = ctx.non_empty_dir() + ctx.termslash() 61 | 62 | ctx.open_file(indirect, ro=1, app=1, err=EISDIR) 63 | ctx.open_file(indirect, ro=1) 64 | ctx.open_file(indirect, ro=1, app=1, err=EISDIR) 65 | ctx.open_file(indirect, ro=1) 66 | -------------------------------------------------------------------------------- /tests/dir-sym2-weird-open.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through indirect symlink of existing directory; with create, exclusive 6 | # and truncate 7 | # 8 | ############################################################################### 9 | 10 | # Open(dir symlink) read-only and create 11 | def subtest_1(ctx): 12 | """Open(dir symlink) O_RDONLY | O_CREAT""" 13 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 14 | direct = ctx.direct_dir_sym() + ctx.termslash() 15 | f = ctx.non_empty_dir() + ctx.termslash() 16 | 17 | ctx.open_file(indirect, ro=1, crt=1, err=EISDIR) 18 | ctx.open_file(indirect, ro=1) 19 | 20 | # Open(dir symlink) read-only and create exclusive 21 | def subtest_2(ctx): 22 | """Open(dir symlink) O_RDONLY | O_CREAT | O_EXCL""" 23 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 24 | direct = ctx.direct_dir_sym() + ctx.termslash() 25 | f = ctx.non_empty_dir() + ctx.termslash() 26 | 27 | ctx.open_file(indirect, ro=1, crt=1, ex=1, err=EEXIST) 28 | ctx.open_file(indirect, ro=1) 29 | 30 | # Open(dir symlink) read-only and truncate 31 | def subtest_3(ctx): 32 | """Open(dir symlink) O_RDONLY | O_TRUNC""" 33 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 34 | direct = ctx.direct_dir_sym() + ctx.termslash() 35 | f = ctx.non_empty_dir() + ctx.termslash() 36 | 37 | ctx.open_file(indirect, ro=1, tr=1, err=EISDIR) 38 | ctx.open_file(indirect, ro=1) 39 | 40 | # Open(dir symlink) read-only and truncate create 41 | def subtest_4(ctx): 42 | """Open(dir symlink) O_RDONLY | O_TRUNC | O_CREAT""" 43 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 44 | direct = ctx.direct_dir_sym() + ctx.termslash() 45 | f = ctx.non_empty_dir() + ctx.termslash() 46 | 47 | ctx.open_file(indirect, ro=1, tr=1, crt=1, err=EISDIR) 48 | ctx.open_file(indirect, ro=1) 49 | 50 | # Open(dir symlink) read-only and truncate create exclusive 51 | def subtest_5(ctx): 52 | """Open(dir symlink) O_RDONLY | O_TRUNC | O_CREAT | O_EXCL""" 53 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 54 | direct = ctx.direct_dir_sym() + ctx.termslash() 55 | f = ctx.non_empty_dir() + ctx.termslash() 56 | 57 | ctx.open_file(indirect, ro=1, tr=1, crt=1, ex=1, err=EEXIST) 58 | ctx.open_file(indirect, ro=1) 59 | 60 | # Open(dir symlink) write-only and create 61 | def subtest_6(ctx): 62 | """Open(dir symlink) O_WRONLY | O_CREAT""" 63 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 64 | direct = ctx.direct_dir_sym() + ctx.termslash() 65 | f = ctx.non_empty_dir() + ctx.termslash() 66 | 67 | ctx.open_file(indirect, wo=1, crt=1, err=EISDIR) 68 | ctx.open_file(indirect, ro=1) 69 | 70 | # Open(dir symlink) write-only and create exclusive 71 | def subtest_7(ctx): 72 | """Open(dir symlink) O_WRONLY | O_CREAT | O_EXCL""" 73 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 74 | direct = ctx.direct_dir_sym() + ctx.termslash() 75 | f = ctx.non_empty_dir() + ctx.termslash() 76 | 77 | ctx.open_file(indirect, wo=1, crt=1, ex=1, err=EEXIST) 78 | ctx.open_file(indirect, ro=1) 79 | 80 | # Open(dir symlink) write-only and truncate 81 | def subtest_8(ctx): 82 | """Open(dir symlink) O_WRONLY | O_TRUNC""" 83 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 84 | direct = ctx.direct_dir_sym() + ctx.termslash() 85 | f = ctx.non_empty_dir() + ctx.termslash() 86 | 87 | ctx.open_file(indirect, wo=1, tr=1, err=EISDIR) 88 | ctx.open_file(indirect, ro=1) 89 | 90 | # Open(dir symlink) write-only and truncate create 91 | def subtest_9(ctx): 92 | """Open(dir symlink) O_WRONLY | O_TRUNC | O_CREAT""" 93 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 94 | direct = ctx.direct_dir_sym() + ctx.termslash() 95 | f = ctx.non_empty_dir() + ctx.termslash() 96 | 97 | ctx.open_file(indirect, wo=1, tr=1, crt=1, err=EISDIR) 98 | ctx.open_file(indirect, ro=1) 99 | 100 | # Open(dir symlink) write-only and truncate create exclusive 101 | def subtest_10(ctx): 102 | """Open(dir symlink) O_WRONLY | O_TRUNC | O_CREAT | O_EXCL""" 103 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 104 | direct = ctx.direct_dir_sym() + ctx.termslash() 105 | f = ctx.non_empty_dir() + ctx.termslash() 106 | 107 | ctx.open_file(indirect, wo=1, tr=1, crt=1, ex=1, err=EEXIST) 108 | ctx.open_file(indirect, ro=1) 109 | -------------------------------------------------------------------------------- /tests/dir-weird-open-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing directory; with O_DIRECTORY and create, exclusive and truncate 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only and create 10 | def subtest_1(ctx): 11 | """Open O_DIRECTORY | O_RDONLY | O_CREAT""" 12 | f = ctx.non_empty_dir() + ctx.termslash() 13 | 14 | ctx.open_dir(f, ro=1, crt=1, err=EINVAL) 15 | ctx.open_dir(f, ro=1) 16 | 17 | # Open read-only and create exclusive 18 | def subtest_2(ctx): 19 | """Open O_DIRECTORY | O_RDONLY | O_CREAT | O_EXCL""" 20 | f = ctx.non_empty_dir() + ctx.termslash() 21 | 22 | ctx.open_dir(f, ro=1, crt=1, ex=1, err=EINVAL) 23 | ctx.open_dir(f, ro=1) 24 | 25 | # Open read-only and truncate 26 | def subtest_3(ctx): 27 | """Open O_DIRECTORY | O_RDONLY | O_TRUNC""" 28 | f = ctx.non_empty_dir() + ctx.termslash() 29 | 30 | ctx.open_dir(f, ro=1, tr=1, err=EISDIR) 31 | ctx.open_dir(f, ro=1) 32 | 33 | # Open read-only and truncate create 34 | def subtest_4(ctx): 35 | """Open O_DIRECTORY | O_RDONLY | O_TRUNC | O_CREAT""" 36 | f = ctx.non_empty_dir() + ctx.termslash() 37 | 38 | ctx.open_dir(f, ro=1, tr=1, crt=1, err=EINVAL) 39 | ctx.open_dir(f, ro=1) 40 | 41 | # Open read-only and truncate create exclusive 42 | def subtest_5(ctx): 43 | """Open O_DIRECTORY | O_RDONLY | O_TRUNC | O_CREAT | O_EXCL""" 44 | f = ctx.non_empty_dir() + ctx.termslash() 45 | 46 | ctx.open_dir(f, ro=1, tr=1, crt=1, ex=1, err=EINVAL) 47 | ctx.open_dir(f, ro=1) 48 | 49 | # Open write-only and create 50 | def subtest_6(ctx): 51 | """Open O_DIRECTORY | O_RDONLY | O_CREAT""" 52 | f = ctx.non_empty_dir() + ctx.termslash() 53 | 54 | ctx.open_dir(f, wo=1, crt=1, err=EINVAL) 55 | ctx.open_dir(f, ro=1) 56 | 57 | # Open write-only and create exclusive 58 | def subtest_7(ctx): 59 | """Open O_DIRECTORY | O_RDONLY | O_CREAT | O_EXCL""" 60 | f = ctx.non_empty_dir() + ctx.termslash() 61 | 62 | ctx.open_dir(f, wo=1, crt=1, ex=1, err=EINVAL) 63 | ctx.open_dir(f, ro=1) 64 | 65 | # Open write-only and truncate 66 | def subtest_8(ctx): 67 | """Open O_DIRECTORY | O_RDONLY | O_TRUNC""" 68 | f = ctx.non_empty_dir() + ctx.termslash() 69 | 70 | ctx.open_dir(f, wo=1, tr=1, err=EISDIR) 71 | ctx.open_dir(f, ro=1) 72 | 73 | # Open write-only and truncate create 74 | def subtest_9(ctx): 75 | """Open O_DIRECTORY | O_RDONLY | O_TRUNC | O_CREAT""" 76 | f = ctx.non_empty_dir() + ctx.termslash() 77 | 78 | ctx.open_dir(f, wo=1, tr=1, crt=1, err=EINVAL) 79 | ctx.open_dir(f, ro=1) 80 | 81 | # Open write-only and truncate create exclusive 82 | def subtest_10(ctx): 83 | """Open O_DIRECTORY | O_RDONLY | O_TRUNC | O_CREAT | O_EXCL""" 84 | f = ctx.non_empty_dir() + ctx.termslash() 85 | 86 | ctx.open_dir(f, wo=1, tr=1, crt=1, ex=1, err=EINVAL) 87 | ctx.open_dir(f, ro=1) 88 | -------------------------------------------------------------------------------- /tests/dir-weird-open.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing directory; with create, exclusive and truncate 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only and create 10 | def subtest_1(ctx): 11 | """Open O_RDONLY | O_CREAT""" 12 | f = ctx.non_empty_dir() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, err=EISDIR) 15 | ctx.open_file(f, ro=1) 16 | 17 | # Open read-only and create exclusive 18 | def subtest_2(ctx): 19 | """Open O_RDONLY | O_CREAT | O_EXCL""" 20 | f = ctx.non_empty_dir() + ctx.termslash() 21 | 22 | ctx.open_file(f, ro=1, crt=1, ex=1, err=EEXIST) 23 | ctx.open_file(f, ro=1) 24 | 25 | # Open read-only and truncate 26 | def subtest_3(ctx): 27 | """Open O_RDONLY | O_TRUNC""" 28 | f = ctx.non_empty_dir() + ctx.termslash() 29 | 30 | ctx.open_file(f, ro=1, tr=1, err=EISDIR) 31 | ctx.open_file(f, ro=1) 32 | 33 | # Open read-only and truncate create 34 | def subtest_4(ctx): 35 | """Open O_RDONLY | O_TRUNC | O_CREAT""" 36 | f = ctx.non_empty_dir() + ctx.termslash() 37 | 38 | ctx.open_file(f, ro=1, tr=1, crt=1, err=EISDIR) 39 | ctx.open_file(f, ro=1) 40 | 41 | # Open read-only and truncate create exclusive 42 | def subtest_5(ctx): 43 | """Open O_RDONLY | O_TRUNC | O_CREAT | O_EXCL""" 44 | f = ctx.non_empty_dir() + ctx.termslash() 45 | 46 | ctx.open_file(f, ro=1, tr=1, crt=1, ex=1, err=EEXIST) 47 | ctx.open_file(f, ro=1) 48 | 49 | # Open write-only and create 50 | def subtest_6(ctx): 51 | """Open O_RDONLY | O_CREAT""" 52 | f = ctx.non_empty_dir() + ctx.termslash() 53 | 54 | ctx.open_file(f, wo=1, crt=1, err=EISDIR) 55 | ctx.open_file(f, ro=1) 56 | 57 | # Open write-only and create exclusive 58 | def subtest_7(ctx): 59 | """Open O_RDONLY | O_CREAT | O_EXCL""" 60 | f = ctx.non_empty_dir() + ctx.termslash() 61 | 62 | ctx.open_file(f, wo=1, crt=1, ex=1, err=EEXIST) 63 | ctx.open_file(f, ro=1) 64 | 65 | # Open write-only and truncate 66 | def subtest_8(ctx): 67 | """Open O_RDONLY | O_TRUNC""" 68 | f = ctx.non_empty_dir() + ctx.termslash() 69 | 70 | ctx.open_file(f, wo=1, tr=1, err=EISDIR) 71 | ctx.open_file(f, ro=1) 72 | 73 | # Open write-only and truncate create 74 | def subtest_9(ctx): 75 | """Open O_RDONLY | O_TRUNC | O_CREAT""" 76 | f = ctx.non_empty_dir() + ctx.termslash() 77 | 78 | ctx.open_file(f, wo=1, tr=1, crt=1, err=EISDIR) 79 | ctx.open_file(f, ro=1) 80 | 81 | # Open write-only and truncate create exclusive 82 | def subtest_10(ctx): 83 | """Open O_RDONLY | O_TRUNC | O_CREAT | O_EXCL""" 84 | f = ctx.non_empty_dir() + ctx.termslash() 85 | 86 | ctx.open_file(f, wo=1, tr=1, crt=1, ex=1, err=EEXIST) 87 | ctx.open_file(f, ro=1) 88 | -------------------------------------------------------------------------------- /tests/hard-link-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to hardlink directories 6 | # 7 | ############################################################################### 8 | 9 | # Hard link a directory 10 | def subtest_1(ctx): 11 | """Hard link dir""" 12 | d = ctx.empty_dir() + ctx.termslash() 13 | d2 = ctx.no_dir() + ctx.termslash() 14 | 15 | ctx.link(d, d2, err=EPERM) 16 | ctx.open_dir(d, ro=1) 17 | ctx.open_dir(d2, ro=1, err=ENOENT) 18 | 19 | # Hard link a file over a directory 20 | def subtest_2(ctx): 21 | """Hard link file over dir""" 22 | f = ctx.reg_file() + ctx.termslash() 23 | d = ctx.empty_dir() + ctx.termslash() 24 | 25 | ctx.link(f, d, err=EEXIST) 26 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 27 | ctx.open_dir(d, ro=1) 28 | 29 | # Hard link a directory over a directory 30 | def subtest_3(ctx): 31 | """Hard link dir over dir""" 32 | d = ctx.non_empty_dir() + ctx.termslash() 33 | d2 = ctx.empty_dir() + ctx.termslash() 34 | 35 | ctx.link(d, d2, err=EEXIST) 36 | ctx.open_dir(d, ro=1) 37 | ctx.open_dir(d2, ro=1) 38 | 39 | # Hard link a directory over a file 40 | def subtest_4(ctx): 41 | """Hard link dir over dir""" 42 | d = ctx.non_empty_dir() + ctx.termslash() 43 | f = ctx.reg_file() + ctx.termslash() 44 | 45 | ctx.link(d, f, err=EEXIST) 46 | ctx.open_dir(d, ro=1) 47 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 48 | 49 | # Hard link a directory over itself 50 | def subtest_5(ctx): 51 | """Hard link dir over itself""" 52 | d = ctx.non_empty_dir() + ctx.termslash() 53 | 54 | ctx.link(d, d, err=EEXIST) 55 | ctx.open_dir(d, ro=1) 56 | 57 | # Hard link a directory over its parent 58 | def subtest_6(ctx): 59 | """Hard link dir over its parent""" 60 | d = ctx.non_empty_dir() + "/pop" + ctx.termslash() 61 | d2 = ctx.non_empty_dir() + ctx.termslash() 62 | 63 | ctx.link(d, d2, err=EEXIST) 64 | ctx.open_dir(d, ro=1) 65 | ctx.open_dir(d2, ro=1) 66 | 67 | # Hard link a removed directory 68 | def subtest_7(ctx): 69 | """Hard link removed dir""" 70 | d = ctx.empty_dir() + ctx.termslash() 71 | d2 = ctx.no_dir() + ctx.termslash() 72 | 73 | ctx.rmdir(d) 74 | ctx.link(d, d2, err=ENOENT) 75 | ctx.open_dir(d, ro=1, err=ENOENT) 76 | ctx.open_dir(d2, ro=1, err=ENOENT) 77 | 78 | # Hard link a renamed directory 79 | def subtest_8(ctx): 80 | """Hard link renamed dir""" 81 | d = ctx.empty_dir() + "/new" + ctx.termslash() 82 | d2 = ctx.no_dir() + ctx.termslash() 83 | d3 = ctx.no_dir() + "-a" + ctx.termslash() 84 | 85 | ctx.mkdir(d, 0o755) 86 | ctx.rename(d, d2) 87 | ctx.link(d, d3, err=ENOENT) 88 | ctx.link(d2, d, err=EPERM) 89 | ctx.open_dir(d, ro=1, err=ENOENT) 90 | ctx.open_dir(d2, ro=1) 91 | ctx.open_dir(d3, ro=1, err=ENOENT) 92 | -------------------------------------------------------------------------------- /tests/hard-link-sym.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to hardlink symlinks 6 | # 7 | ############################################################################### 8 | 9 | # Hard link a symlink 10 | def subtest_1(ctx): 11 | """Hard link symlink""" 12 | f = ctx.direct_sym() + ctx.termslash() 13 | f2 = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.link(f, f2) 16 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 17 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 18 | 19 | # Hard link a dangling symlink 20 | def subtest_2(ctx): 21 | """Hard link dangling symlink""" 22 | f = ctx.pointless() + ctx.termslash() 23 | f2 = ctx.no_file() + ctx.termslash() 24 | 25 | ctx.link(f, f2) 26 | ctx.open_file(f, ro=1, err=ELOOP) 27 | ctx.open_file(f2, ro=1, err=ELOOP) 28 | 29 | # Hard link a non-existent file over a symlink 30 | def subtest_3(ctx): 31 | """Hard link non-existent file over a symlink""" 32 | f = ctx.no_file() + ctx.termslash() 33 | f2 = ctx.direct_sym() + ctx.termslash() 34 | 35 | ctx.link(f, f2, err=ENOENT) 36 | ctx.open_file(f, ro=1, err=ENOENT) 37 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 38 | 39 | # Hard link a symlink over a file 40 | def subtest_4(ctx): 41 | """Hard link symlink over file""" 42 | f = ctx.direct_sym() + ctx.termslash() 43 | f2 = ctx.non_empty_dir() + "/a" + ctx.termslash() 44 | 45 | ctx.link(f, f2, err=EEXIST) 46 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 47 | ctx.open_file(f2, ro=1, read="") 48 | 49 | # Hard link a symlink over a new file 50 | def subtest_5(ctx): 51 | """Hard link symlink over new file""" 52 | f = ctx.direct_sym() + ctx.termslash() 53 | f2 = ctx.reg_file() + "-new" + ctx.termslash() 54 | 55 | ctx.open_file(f2, wo=1, crt=1, write="aaaa") 56 | ctx.link(f, f2, err=EEXIST) 57 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 58 | ctx.open_file(f2, ro=1, read="aaaa") 59 | 60 | # Hard link a new file over a symlink 61 | def subtest_6(ctx): 62 | """Hard link new file over symlink""" 63 | f = ctx.reg_file() + "-new" + ctx.termslash() 64 | f2 = ctx.direct_sym() + ctx.termslash() 65 | 66 | ctx.open_file(f, wo=1, crt=1, write="aaaa") 67 | ctx.link(f, f2, err=EEXIST) 68 | ctx.open_file(f, ro=1, read="aaaa") 69 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 70 | 71 | # Hard link a symlink over itself 72 | def subtest_7(ctx): 73 | """Hard link symlink over itself""" 74 | f = ctx.direct_sym() + ctx.termslash() 75 | 76 | ctx.link(f, f, err=EEXIST) 77 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 78 | 79 | # Hard link a symlink over another symlink 80 | def subtest_8(ctx): 81 | """Hard link symlink over another symlink""" 82 | f = ctx.direct_sym() + ctx.termslash() 83 | f2 = ctx.pointless() + ctx.termslash() 84 | 85 | ctx.link(f, f2, err=EEXIST) 86 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 87 | ctx.open_file(f2, ro=1, err=ENOENT) 88 | 89 | # Hard link an unlinked symlink 90 | def subtest_9(ctx): 91 | """Hard link unlinked symlink""" 92 | f = ctx.direct_sym() + ctx.termslash() 93 | f2 = ctx.no_file() + ctx.termslash() 94 | 95 | ctx.unlink(f) 96 | ctx.link(f, f2, err=ENOENT) 97 | ctx.open_file(f, ro=1, err=ENOENT) 98 | ctx.open_file(f2, ro=1, err=ENOENT) 99 | 100 | # Hard link a renamed symlink 101 | def subtest_10(ctx): 102 | """Hard link renamed symlink""" 103 | f = ctx.direct_sym() + ctx.termslash() 104 | f2 = ctx.no_file() + ctx.termslash() 105 | f3 = ctx.no_file() + "-a" + ctx.termslash() 106 | 107 | ctx.rename(f, f2) 108 | ctx.link(f, f3, err=ENOENT) 109 | ctx.link(f2, f) 110 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 111 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 112 | ctx.open_file(f3, ro=1, err=ENOENT) 113 | -------------------------------------------------------------------------------- /tests/hard-link.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to hardlink files 6 | # 7 | ############################################################################### 8 | 9 | # Hard link a file 10 | def subtest_1(ctx): 11 | """Hard link file""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | f2 = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.link(f, f2) 16 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 17 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 18 | 19 | # Hard link a non-existent file 20 | def subtest_2(ctx): 21 | """Hard link non-existent file""" 22 | f = ctx.no_file() + ctx.termslash() 23 | f2 = ctx.no_file() + "a" + ctx.termslash() 24 | 25 | ctx.link(f, f2, err=ENOENT) 26 | ctx.open_file(f, ro=1, err=ENOENT) 27 | ctx.open_file(f2, ro=1, err=ENOENT) 28 | 29 | # Hard link a non-existent file over a real file 30 | def subtest_3(ctx): 31 | """Hard link non-existent file over a file""" 32 | f = ctx.no_file() + ctx.termslash() 33 | f2 = ctx.reg_file() + ctx.termslash() 34 | 35 | ctx.link(f, f2, err=ENOENT) 36 | ctx.open_file(f, ro=1, err=ENOENT) 37 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 38 | 39 | # Hard link a file over another file 40 | def subtest_4(ctx): 41 | """Hard link file over file""" 42 | f = ctx.reg_file() + ctx.termslash() 43 | f2 = ctx.non_empty_dir() + "/a" + ctx.termslash() 44 | 45 | ctx.link(f, f2, err=EEXIST) 46 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 47 | ctx.open_file(f2, ro=1, read="") 48 | 49 | # Hard link a file over a new file 50 | def subtest_5(ctx): 51 | """Hard link file over new file""" 52 | f = ctx.reg_file() + ctx.termslash() 53 | f2 = ctx.reg_file() + "-new" + ctx.termslash() 54 | 55 | ctx.open_file(f2, wo=1, crt=1, write="aaaa") 56 | ctx.link(f, f2, err=EEXIST) 57 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 58 | ctx.open_file(f2, ro=1, read="aaaa") 59 | 60 | # Hard link a new file over a lower file 61 | def subtest_6(ctx): 62 | """Hard link new file over lower file""" 63 | f = ctx.reg_file() + "-new" + ctx.termslash() 64 | f2 = ctx.reg_file() + ctx.termslash() 65 | 66 | ctx.open_file(f, wo=1, crt=1, write="aaaa") 67 | ctx.link(f, f2, err=EEXIST) 68 | ctx.open_file(f, ro=1, read="aaaa") 69 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 70 | 71 | # Hard link a file over itself 72 | def subtest_7(ctx): 73 | """Hard link file over itself""" 74 | f = ctx.reg_file() + ctx.termslash() 75 | 76 | ctx.link(f, f, err=EEXIST) 77 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 78 | 79 | # Hard link a new file over itself 80 | def subtest_8(ctx): 81 | """Hard link new file over itself""" 82 | f = ctx.reg_file() + "-new" + ctx.termslash() 83 | 84 | ctx.open_file(f, wo=1, crt=1, write="aaaa") 85 | ctx.link(f, f, err=EEXIST) 86 | ctx.open_file(f, ro=1, read="aaaa") 87 | 88 | # Hard link a non-existent file over itself 89 | def subtest_9(ctx): 90 | """Hard link non-existent file over itself""" 91 | f = ctx.no_file() + ctx.termslash() 92 | 93 | ctx.link(f, f, err=ENOENT) 94 | ctx.open_file(f, ro=1, err=ENOENT) 95 | 96 | # Hard link an unlinked file 97 | def subtest_10(ctx): 98 | """Hard link unlinked file""" 99 | f = ctx.reg_file() + ctx.termslash() 100 | f2 = ctx.no_file() + ctx.termslash() 101 | 102 | ctx.unlink(f) 103 | ctx.link(f, f2, err=ENOENT) 104 | ctx.open_file(f, ro=1, err=ENOENT) 105 | ctx.open_file(f2, ro=1, err=ENOENT) 106 | 107 | # Hard link a renamed file 108 | def subtest_11(ctx): 109 | """Hard link renamed file""" 110 | f = ctx.reg_file() + ctx.termslash() 111 | f2 = ctx.no_file() + ctx.termslash() 112 | f3 = ctx.no_file() + "-a" + ctx.termslash() 113 | 114 | ctx.rename(f, f2) 115 | ctx.link(f, f3, err=ENOENT) 116 | ctx.link(f2, f) 117 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 118 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 119 | ctx.open_file(f3, ro=1, err=ENOENT) 120 | -------------------------------------------------------------------------------- /tests/impermissible.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to violate permissions 6 | # 7 | ############################################################################### 8 | 9 | def subtest_1(ctx): 10 | """Impermissible open O_TRUNC|O_WRONLY""" 11 | f = ctx.rootfile() + ctx.termslash() 12 | 13 | ctx.open_file(f, wo=1, tr=1, err=EACCES, as_bin=1) 14 | ctx.open_file(f, wo=1, err=EACCES, as_bin=1) 15 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz", as_bin=1) 16 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 17 | ctx.open_file(f, wo=1, write="shark") 18 | ctx.open_file(f, ro=1, read="sharkyyy:zzz") 19 | ctx.open_file(f, ro=1, read="sharkyyy:zzz", as_bin=1) 20 | 21 | def subtest_2(ctx): 22 | """Impermissible open O_WRONLY""" 23 | f = ctx.rootfile() + ctx.termslash() 24 | 25 | ctx.open_file(f, wo=1, err=EACCES, as_bin=1) 26 | ctx.open_file(f, wo=1, err=EACCES, as_bin=1) 27 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz", as_bin=1) 28 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 29 | ctx.open_file(f, wo=1, write="shark") 30 | ctx.open_file(f, ro=1, read="sharkyyy:zzz") 31 | ctx.open_file(f, ro=1, read="sharkyyy:zzz", as_bin=1) 32 | 33 | def subtest_3(ctx): 34 | """Impermissible open O_APPEND""" 35 | f = ctx.rootfile() + ctx.termslash() 36 | 37 | ctx.open_file(f, app=1, err=EACCES, as_bin=1) 38 | ctx.open_file(f, app=1, err=EACCES, as_bin=1) 39 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz", as_bin=1) 40 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 41 | ctx.open_file(f, app=1, write="shark") 42 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzzshark") 43 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzzshark", as_bin=1) 44 | 45 | # 46 | # 47 | # 48 | def subtest_4(ctx): 49 | """Impermissible truncate""" 50 | f = ctx.rootfile() + ctx.termslash() 51 | 52 | if not ctx.termslash(): 53 | size = ctx.get_file_size(f) 54 | if size != 12: 55 | raise TestError(f + ": Initial size (" + str(size) + ") is not 12") 56 | ctx.truncate(f, 4, err=EACCES, as_bin=1) 57 | ctx.truncate(f, 4, err=EACCES, as_bin=1) 58 | if not ctx.termslash(): 59 | size = ctx.get_file_size(f) 60 | if size != 12: 61 | raise TestError(f + ": Size (" + str(size) + ") is not still 12") 62 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz", as_bin=1) 63 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 64 | ctx.truncate(f, 4) 65 | if not ctx.termslash(): 66 | size = ctx.get_file_size(f) 67 | if size != 4: 68 | raise TestError(f + ": Size (" + str(size) + ") is not 4") 69 | ctx.open_file(f, ro=1, read=":xxx") 70 | ctx.open_file(f, ro=1, read=":xxx", as_bin=1) 71 | 72 | # 73 | # 74 | # 75 | def subtest_5(ctx): 76 | """Impermissible utimes""" 77 | f = ctx.rootfile() + ctx.termslash() 78 | 79 | if not ctx.termslash(): 80 | atime = ctx.get_file_atime(f) 81 | mtime = ctx.get_file_mtime(f) 82 | ctx.utimes(f, err=EACCES, as_bin=1) 83 | ctx.utimes(f, err=EACCES, as_bin=1) 84 | if not ctx.termslash(): 85 | if ctx.get_file_atime(f) != atime: 86 | raise TestError(f + ": Access time unexpectedly changed") 87 | if ctx.get_file_mtime(f) != mtime: 88 | raise TestError(f + ": Modification time unexpectedly changed") 89 | ctx.utimes(f) 90 | if not ctx.termslash(): 91 | if ctx.get_file_atime(f) == atime: 92 | raise TestError(f + ": Access time didn't change") 93 | if ctx.get_file_mtime(f) == mtime: 94 | raise TestError(f + ": Modification time didn't change") 95 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 96 | -------------------------------------------------------------------------------- /tests/mkdir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to create directories 6 | # 7 | ############################################################################### 8 | 9 | # Create a directory that does not exist in the lower layer 10 | def subtest_1(ctx): 11 | """Create directory""" 12 | d = ctx.no_dir() + ctx.termslash() 13 | 14 | ctx.mkdir(d, 0o755) 15 | ctx.mkdir(d, 0o755, err=EEXIST) 16 | 17 | # Create a directory over a file 18 | def subtest_2(ctx): 19 | """Create directory over file""" 20 | f = ctx.reg_file() 21 | d = ctx.reg_file() + ctx.termslash() 22 | 23 | ctx.mkdir(d, 0o755, err=EEXIST) 24 | ctx.mkdir(d, 0o755, err=EEXIST) 25 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 26 | 27 | # Create a directory over an empty lower directory 28 | def subtest_3(ctx): 29 | """Create directory over empty dir""" 30 | d = ctx.empty_dir() + ctx.termslash() 31 | 32 | ctx.mkdir(d, 0o755, err=EEXIST) 33 | 34 | # Create a directory in an empty lower directory 35 | def subtest_4(ctx): 36 | """Create directory in empty dir""" 37 | d = ctx.empty_dir() + "/sub" + ctx.termslash() 38 | 39 | ctx.mkdir(d, 0o755) 40 | ctx.mkdir(d, 0o755, err=EEXIST) 41 | 42 | # Create a directory over a populated lower directory 43 | def subtest_5(ctx): 44 | """Create directory over dir""" 45 | d = ctx.non_empty_dir() + ctx.termslash() 46 | 47 | ctx.mkdir(d, 0o755, err=EEXIST) 48 | ctx.open_file(d + "/a", ro=1, read="") 49 | 50 | # Create a directory in a populated lower directory 51 | def subtest_6(ctx): 52 | """Create directory in dir""" 53 | d = ctx.non_empty_dir() + ctx.termslash() 54 | subdir = ctx.non_empty_dir() + "/sub" + ctx.termslash() 55 | 56 | ctx.mkdir(subdir, 0o755) 57 | ctx.mkdir(subdir, 0o755, err=EEXIST) 58 | ctx.open_file(d + "/a", ro=1, read="") 59 | 60 | # Create a directory over a symlink to a file 61 | def subtest_7(ctx): 62 | """Create directory over sym to file""" 63 | f = ctx.reg_file() 64 | d = ctx.reg_file() + ctx.termslash() 65 | sym = ctx.direct_sym() + ctx.termslash() 66 | 67 | ctx.mkdir(sym, 0o755, err=EEXIST) 68 | ctx.mkdir(sym, 0o755, err=EEXIST) 69 | ctx.mkdir(d, 0o755, err=EEXIST) 70 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 71 | 72 | # Create a directory over a symlink to a symlink to a file 73 | def subtest_8(ctx): 74 | """Create directory over sym to sym to file""" 75 | f = ctx.reg_file() 76 | d = ctx.reg_file() + ctx.termslash() 77 | sym = ctx.direct_sym() + ctx.termslash() 78 | isym = ctx.indirect_sym() + ctx.termslash() 79 | 80 | ctx.mkdir(isym, 0o755, err=EEXIST) 81 | ctx.mkdir(isym, 0o755, err=EEXIST) 82 | ctx.mkdir(sym, 0o755, err=EEXIST) 83 | ctx.mkdir(d, 0o755, err=EEXIST) 84 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 85 | 86 | # Create a directory over a symlink to a dir 87 | def subtest_9(ctx): 88 | """Create directory over sym to dir""" 89 | d = ctx.non_empty_dir() + ctx.termslash() 90 | sym = ctx.direct_dir_sym() + ctx.termslash() 91 | 92 | ctx.mkdir(sym, 0o755, err=EEXIST) 93 | ctx.mkdir(sym, 0o755, err=EEXIST) 94 | ctx.mkdir(d, 0o755, err=EEXIST) 95 | ctx.open_file(sym + "/a", ro=1, read="") 96 | ctx.open_file(d + "/a", ro=1, read="") 97 | 98 | # Create a directory over a symlink to a symlink to a dir 99 | def subtest_10(ctx): 100 | """Create directory over sym to sym to dir""" 101 | d = ctx.non_empty_dir() + ctx.termslash() 102 | sym = ctx.direct_dir_sym() + ctx.termslash() 103 | isym = ctx.indirect_dir_sym() + ctx.termslash() 104 | 105 | ctx.mkdir(isym, 0o755, err=EEXIST) 106 | ctx.mkdir(isym, 0o755, err=EEXIST) 107 | ctx.mkdir(sym, 0o755, err=EEXIST) 108 | ctx.mkdir(d, 0o755, err=EEXIST) 109 | ctx.open_file(isym + "/a", ro=1, read="") 110 | ctx.open_file(sym + "/a", ro=1, read="") 111 | ctx.open_file(d + "/a", ro=1, read="") 112 | 113 | # Create a directory over a dangling symlink 114 | def subtest_11(ctx): 115 | """Create directory over dangling sym""" 116 | d = ctx.no_file() + ctx.termslash() 117 | sym = ctx.pointless() + ctx.termslash() 118 | 119 | ctx.mkdir(sym, 0o755, err=EEXIST) 120 | ctx.mkdir(sym, 0o755, err=EEXIST) 121 | -------------------------------------------------------------------------------- /tests/noent-creat-excl-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Creation of a not-yet existent file with O_CREAT|O_EXCL and O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Create O_CREAT|O_EXCL|O_TRUNC|O_RDONLY""" 12 | f = ctx.no_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, ex=1, tr=1, read="") 15 | ctx.open_file(f, ro=1, crt=1, ex=1, tr=1, err=EEXIST) 16 | ctx.open_file(f, ro=1, read="") 17 | 18 | # Open write-only and overwrite 19 | def subtest_2(ctx): 20 | """Create O_CREAT|O_EXCL|O_TRUNC|O_WRONLY""" 21 | f = ctx.no_file() + ctx.termslash() 22 | 23 | ctx.open_file(f, wo=1, crt=1, ex=1, tr=1, write="q") 24 | ctx.open_file(f, ro=1, read="q") 25 | ctx.open_file(f, wo=1, crt=1, ex=1, tr=1, err=EEXIST) 26 | ctx.open_file(f, ro=1, read="q") 27 | 28 | # Open write-only and append 29 | def subtest_3(ctx): 30 | """Create O_CREAT|O_EXCL|O_TRUNC|O_APPEND|O_WRONLY""" 31 | f = ctx.no_file() + ctx.termslash() 32 | 33 | ctx.open_file(f, app=1, crt=1, ex=1, tr=1, write="q") 34 | ctx.open_file(f, ro=1, read="q") 35 | ctx.open_file(f, app=1, crt=1, ex=1, err=EEXIST) 36 | ctx.open_file(f, ro=1, read="q") 37 | 38 | # Open read/write and overwrite 39 | def subtest_4(ctx): 40 | """Create O_CREAT|O_EXCL|O_TRUNC|O_RDWR""" 41 | f = ctx.no_file() + ctx.termslash() 42 | 43 | ctx.open_file(f, rw=1, crt=1, ex=1, tr=1, write="q") 44 | ctx.open_file(f, ro=1, read="q") 45 | ctx.open_file(f, rw=1, crt=1, ex=1, err=EEXIST) 46 | ctx.open_file(f, ro=1, read="q") 47 | 48 | # Open read/write and append 49 | def subtest_5(ctx): 50 | """Create O_CREAT|O_EXCL|O_TRUNC|O_APPEND|O_RDWR""" 51 | f = ctx.no_file() + ctx.termslash() 52 | 53 | ctx.open_file(f, ro=1, app=1, crt=1, ex=1, tr=1, write="q") 54 | ctx.open_file(f, ro=1, read="q") 55 | ctx.open_file(f, ro=1, app=1, crt=1, ex=1, err=EEXIST) 56 | ctx.open_file(f, ro=1, read="q") 57 | -------------------------------------------------------------------------------- /tests/noent-creat-excl.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Creation of a not-yet existent file with O_CREAT and O_EXCL 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Create O_CREAT|O_EXCL|O_RDONLY""" 12 | f = ctx.no_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, ex=1, read="") 15 | ctx.open_file(f, ro=1, crt=1, ex=1, err=EEXIST) 16 | ctx.open_file(f, ro=1, read="") 17 | 18 | # Open write-only and overwrite 19 | def subtest_2(ctx): 20 | """Create O_CREAT|O_EXCL|O_WRONLY""" 21 | f = ctx.no_file() + ctx.termslash() 22 | 23 | ctx.open_file(f, wo=1, crt=1, ex=1, write="q") 24 | ctx.open_file(f, ro=1, read="q") 25 | ctx.open_file(f, wo=1, crt=1, ex=1, err=EEXIST) 26 | ctx.open_file(f, ro=1, read="q") 27 | 28 | # Open write-only and append 29 | def subtest_3(ctx): 30 | """Create O_CREAT|O_EXCL|O_APPEND|O_WRONLY""" 31 | f = ctx.no_file() + ctx.termslash() 32 | 33 | ctx.open_file(f, app=1, crt=1, ex=1, write="q") 34 | ctx.open_file(f, ro=1, read="q") 35 | ctx.open_file(f, app=1, crt=1, ex=1, err=EEXIST) 36 | ctx.open_file(f, ro=1, read="q") 37 | 38 | # Open read/write and overwrite 39 | def subtest_4(ctx): 40 | """Create O_CREAT|O_EXCL|O_RDWR""" 41 | f = ctx.no_file() + ctx.termslash() 42 | 43 | ctx.open_file(f, rw=1, crt=1, ex=1, write="q") 44 | ctx.open_file(f, ro=1, read="q") 45 | ctx.open_file(f, rw=1, crt=1, ex=1, err=EEXIST) 46 | ctx.open_file(f, ro=1, read="q") 47 | 48 | # Open read/write and append 49 | def subtest_5(ctx): 50 | """Create O_CREAT|O_EXCL|O_APPEND|O_RDWR""" 51 | f = ctx.no_file() + ctx.termslash() 52 | 53 | ctx.open_file(f, ro=1, app=1, crt=1, ex=1, write="q") 54 | ctx.open_file(f, ro=1, read="q") 55 | ctx.open_file(f, ro=1, app=1, crt=1, ex=1, err=EEXIST) 56 | ctx.open_file(f, ro=1, read="q") 57 | -------------------------------------------------------------------------------- /tests/noent-creat-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Creation of a not-yet existent file with O_CREAT and O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Create O_CREAT|O_TRUNC|O_RDONLY""" 12 | f = ctx.no_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, tr=1, read="") 15 | ctx.open_file(f, ro=1, crt=1, tr=1, read="") 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Create O_CREAT|O_TRUNC|O_WRONLY""" 20 | f = ctx.no_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, crt=1, tr=1, write="q") 23 | ctx.open_file(f, ro=1, read="q") 24 | ctx.open_file(f, wo=1, crt=1, tr=1, write="p") 25 | ctx.open_file(f, ro=1, read="p") 26 | 27 | # Open write-only and append 28 | def subtest_3(ctx): 29 | """Create O_CREAT|O_TRUNC|O_APPEND|O_WRONLY""" 30 | f = ctx.no_file() + ctx.termslash() 31 | 32 | ctx.open_file(f, app=1, crt=1, tr=1, write="q") 33 | ctx.open_file(f, ro=1, read="q") 34 | ctx.open_file(f, app=1, crt=1, write="p") 35 | ctx.open_file(f, ro=1, read="qp") 36 | 37 | # Open read/write and overwrite 38 | def subtest_4(ctx): 39 | """Create O_CREAT|O_TRUNC|O_RDWR""" 40 | f = ctx.no_file() + ctx.termslash() 41 | 42 | ctx.open_file(f, rw=1, crt=1, tr=1, write="q") 43 | ctx.open_file(f, ro=1, read="q") 44 | ctx.open_file(f, rw=1, crt=1, write="p") 45 | ctx.open_file(f, ro=1, read="p") 46 | 47 | # Open read/write and append 48 | def subtest_5(ctx): 49 | """Create O_CREAT|O_TRUNC|O_APPEND|O_RDWR""" 50 | f = ctx.no_file() + ctx.termslash() 51 | 52 | ctx.open_file(f, ro=1, app=1, crt=1, tr=1, write="q") 53 | ctx.open_file(f, ro=1, read="q") 54 | ctx.open_file(f, ro=1, app=1, crt=1, write="p") 55 | ctx.open_file(f, ro=1, read="qp") 56 | -------------------------------------------------------------------------------- /tests/noent-creat.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Creation of a not-yet existent file with O_CREAT 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Create O_CREAT|O_RDONLY""" 12 | f = ctx.no_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, read="") 15 | ctx.open_file(f, ro=1, crt=1, read="") 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Create O_CREAT|O_WRONLY""" 20 | f = ctx.no_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, crt=1, write="q") 23 | ctx.open_file(f, ro=1, read="q") 24 | ctx.open_file(f, wo=1, crt=1, write="p") 25 | ctx.open_file(f, ro=1, read="p") 26 | 27 | # Open write-only and append 28 | def subtest_3(ctx): 29 | """Create O_CREAT|O_APPEND|O_WRONLY""" 30 | f = ctx.no_file() + ctx.termslash() 31 | 32 | ctx.open_file(f, app=1, crt=1, write="q") 33 | ctx.open_file(f, ro=1, read="q") 34 | ctx.open_file(f, app=1, crt=1, write="p") 35 | ctx.open_file(f, ro=1, read="qp") 36 | 37 | # Open read/write and overwrite 38 | def subtest_4(ctx): 39 | """Create O_CREAT|O_RDWR""" 40 | f = ctx.no_file() + ctx.termslash() 41 | 42 | ctx.open_file(f, rw=1, crt=1, write="q") 43 | ctx.open_file(f, ro=1, read="q") 44 | ctx.open_file(f, rw=1, crt=1, write="p") 45 | ctx.open_file(f, ro=1, read="p") 46 | 47 | # Open read/write and append 48 | def subtest_5(ctx): 49 | """Create O_CREAT|O_APPEND|O_RDWR""" 50 | f = ctx.no_file() + ctx.termslash() 51 | 52 | ctx.open_file(f, ro=1, app=1, crt=1, write="q") 53 | ctx.open_file(f, ro=1, read="q") 54 | ctx.open_file(f, ro=1, app=1, crt=1, write="p") 55 | ctx.open_file(f, ro=1, read="qp") 56 | -------------------------------------------------------------------------------- /tests/noent-plain.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Attempted open of non-existent file; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_RDONLY""" 12 | f = ctx.no_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, err=ENOENT) 15 | ctx.open_file(f, ro=1, err=ENOENT) 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_WRONLY""" 20 | f = ctx.no_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, err=ENOENT) 23 | ctx.open_file(f, wo=1, err=ENOENT) 24 | 25 | # Open write-only and append 26 | def subtest_3(ctx): 27 | """Open O_APPEND|O_WRONLY""" 28 | f = ctx.no_file() + ctx.termslash() 29 | 30 | ctx.open_file(f, app=1, err=ENOENT) 31 | ctx.open_file(f, app=1, err=ENOENT) 32 | 33 | # Open read/write and overwrite 34 | def subtest_4(ctx): 35 | """Open O_RDWR""" 36 | f = ctx.no_file() + ctx.termslash() 37 | 38 | ctx.open_file(f, rw=1, err=ENOENT) 39 | ctx.open_file(f, rw=1, err=ENOENT) 40 | 41 | # Open read/write and append 42 | def subtest_5(ctx): 43 | """Open O_APPEND|O_RDWR""" 44 | f = ctx.no_file() + ctx.termslash() 45 | 46 | ctx.open_file(f, ro=1, app=1, err=ENOENT) 47 | ctx.open_file(f, ro=1, app=1, err=ENOENT) 48 | -------------------------------------------------------------------------------- /tests/noent-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Attempted open of non-existent file; O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_TRUNC|O_RDONLY""" 12 | f = ctx.no_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, tr=1, err=ENOENT) 15 | ctx.open_file(f, ro=1, tr=1, err=ENOENT) 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_TRUNC|O_WRONLY""" 20 | f = ctx.no_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, tr=1, err=ENOENT) 23 | ctx.open_file(f, wo=1, tr=1, err=ENOENT) 24 | 25 | # Open write-only and append 26 | def subtest_3(ctx): 27 | """Open O_TRUNC|O_APPEND|O_WRONLY""" 28 | f = ctx.no_file() + ctx.termslash() 29 | 30 | ctx.open_file(f, app=1, tr=1, err=ENOENT) 31 | ctx.open_file(f, app=1, tr=1, err=ENOENT) 32 | 33 | # Open read/write and overwrite 34 | def subtest_4(ctx): 35 | """Open O_TRUNC|O_RDWR""" 36 | f = ctx.no_file() + ctx.termslash() 37 | 38 | ctx.open_file(f, rw=1, tr=1, err=ENOENT) 39 | ctx.open_file(f, rw=1, tr=1, err=ENOENT) 40 | 41 | # Open read/write and append 42 | def subtest_5(ctx): 43 | """Open O_TRUNC|O_APPEND|O_RDWR""" 44 | f = ctx.no_file() + ctx.termslash() 45 | 46 | ctx.open_file(f, ro=1, app=1, tr=1, err=ENOENT) 47 | ctx.open_file(f, ro=1, app=1, tr=1, err=ENOENT) 48 | -------------------------------------------------------------------------------- /tests/open-creat-excl-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing file with O_CREAT, O_EXCL and O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_CREAT|O_EXCL|O_TRUNC|O_RDONLY""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, ex=1, tr=1, err=EEXIST) 15 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_CREAT|O_EXCL|O_TRUNC|O_WRONLY""" 20 | f = ctx.reg_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, crt=1, ex=1, tr=1, err=EEXIST) 23 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 24 | 25 | # Open write-only and append 26 | def subtest_3(ctx): 27 | """Open O_CREAT|O_EXCL|O_TRUNC|O_APPEND|O_WRONLY""" 28 | f = ctx.reg_file() + ctx.termslash() 29 | 30 | ctx.open_file(f, app=1, crt=1, ex=1, tr=1, err=EEXIST) 31 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 32 | 33 | # Open read/write and overwrite 34 | def subtest_4(ctx): 35 | """Open O_CREAT|O_EXCL|O_TRUNC|O_RDWR""" 36 | f = ctx.reg_file() + ctx.termslash() 37 | 38 | ctx.open_file(f, rw=1, crt=1, ex=1, tr=1, err=EEXIST) 39 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 40 | 41 | # Open read/write and append 42 | def subtest_5(ctx): 43 | """Open O_CREAT|O_EXCL|O_TRUNC|O_APPEND|O_RDWR""" 44 | f = ctx.reg_file() + ctx.termslash() 45 | 46 | ctx.open_file(f, ro=1, app=1, crt=1, ex=1, tr=1, err=EEXIST) 47 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 48 | -------------------------------------------------------------------------------- /tests/open-creat-excl.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing file with O_CREAT and O_EXCL 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_CREAT|O_EXCL|O_RDONLY""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, ex=1, err=EEXIST) 15 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_CREAT|O_EXCL|O_WRONLY""" 20 | f = ctx.reg_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, crt=1, ex=1, err=EEXIST) 23 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 24 | 25 | # Open write-only and append 26 | def subtest_3(ctx): 27 | """Open O_CREAT|O_EXCL|O_APPEND|O_WRONLY""" 28 | f = ctx.reg_file() + ctx.termslash() 29 | 30 | ctx.open_file(f, app=1, crt=1, ex=1, err=EEXIST) 31 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 32 | 33 | # Open read/write and overwrite 34 | def subtest_4(ctx): 35 | """Open O_CREAT|O_EXCL|O_RDWR""" 36 | f = ctx.reg_file() + ctx.termslash() 37 | 38 | ctx.open_file(f, rw=1, crt=1, ex=1, err=EEXIST) 39 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 40 | 41 | # Open read/write and append 42 | def subtest_5(ctx): 43 | """Open O_CREAT|O_EXCL|O_APPEND|O_RDWR""" 44 | f = ctx.reg_file() + ctx.termslash() 45 | 46 | ctx.open_file(f, ro=1, app=1, crt=1, ex=1, err=EEXIST) 47 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 48 | -------------------------------------------------------------------------------- /tests/open-creat-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing file with O_CREAT and O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Truncate and open read-only 10 | def subtest_1(ctx): 11 | """Open O_CREAT|O_TRUNC|O_RDONLY""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, tr=1, read="") 15 | ctx.open_file(f, ro=1, crt=1, tr=1, read="") 16 | 17 | # Truncate, open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_CREAT|O_TRUNC|O_WRONLY""" 20 | f = ctx.reg_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, crt=1, tr=1, write="q") 23 | ctx.open_file(f, ro=1, read="q") 24 | ctx.open_file(f, wo=1, crt=1, tr=1, write="p") 25 | ctx.open_file(f, ro=1, read="p") 26 | 27 | # Truncate, open write-only and append 28 | def subtest_3(ctx): 29 | """Open O_CREAT|O_TRUNC|O_APPEND|O_WRONLY""" 30 | f = ctx.reg_file() + ctx.termslash() 31 | 32 | ctx.open_file(f, app=1, crt=1, tr=1, write="q") 33 | ctx.open_file(f, ro=1, read="q") 34 | ctx.open_file(f, app=1, crt=1, tr=1, write="p") 35 | ctx.open_file(f, ro=1, read="p") 36 | 37 | # Truncate, open read/write and overwrite 38 | def subtest_4(ctx): 39 | """Open O_CREAT|O_TRUNC|O_RDWR""" 40 | f = ctx.reg_file() + ctx.termslash() 41 | 42 | ctx.open_file(f, rw=1, crt=1, tr=1, write="q") 43 | ctx.open_file(f, ro=1, read="q") 44 | ctx.open_file(f, rw=1, crt=1, tr=1, write="p") 45 | ctx.open_file(f, ro=1, read="p") 46 | 47 | # Truncate, open read/write and append 48 | def subtest_5(ctx): 49 | """Open O_CREAT|O_TRUNC|O_APPEND|O_RDWR""" 50 | f = ctx.reg_file() + ctx.termslash() 51 | 52 | ctx.open_file(f, ro=1, app=1, crt=1, tr=1, write="q") 53 | ctx.open_file(f, ro=1, read="q") 54 | ctx.open_file(f, ro=1, app=1, crt=1, tr=1, write="p") 55 | ctx.open_file(f, ro=1, read="p") 56 | -------------------------------------------------------------------------------- /tests/open-creat.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing file with O_CREAT 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_CREAT|O_RDONLY""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, crt=1, read=":xxx:yyy:zzz") 15 | ctx.open_file(f, ro=1, crt=1, read=":xxx:yyy:zzz") 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_CREAT|O_WRONLY""" 20 | f = ctx.reg_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, crt=1, write="q") 23 | ctx.open_file(f, ro=1, crt=1, read="qxxx:yyy:zzz") 24 | ctx.open_file(f, wo=1, crt=1, write="p") 25 | ctx.open_file(f, ro=1, crt=1, read="pxxx:yyy:zzz") 26 | 27 | # Open write-only and append 28 | def subtest_3(ctx): 29 | """Open O_CREAT|O_APPEND|O_WRONLY""" 30 | f = ctx.reg_file() + ctx.termslash() 31 | 32 | ctx.open_file(f, app=1, crt=1, write="q") 33 | ctx.open_file(f, ro=1, crt=1, read=":xxx:yyy:zzzq") 34 | ctx.open_file(f, app=1, crt=1, write="p") 35 | ctx.open_file(f, ro=1, crt=1, read=":xxx:yyy:zzzqp") 36 | 37 | # Open read/write and overwrite 38 | def subtest_4(ctx): 39 | """Open O_CREAT|O_RDWR""" 40 | f = ctx.reg_file() + ctx.termslash() 41 | 42 | ctx.open_file(f, rw=1, crt=1, write="q") 43 | ctx.open_file(f, ro=1, crt=1, read="qxxx:yyy:zzz") 44 | ctx.open_file(f, rw=1, crt=1, write="p") 45 | ctx.open_file(f, ro=1, crt=1, read="pxxx:yyy:zzz") 46 | 47 | # Open read/write and append 48 | def subtest_5(ctx): 49 | """Open O_CREAT|O_APPEND|O_RDWR""" 50 | f = ctx.reg_file() + ctx.termslash() 51 | 52 | ctx.open_file(f, ro=1, app=1, crt=1, write="q") 53 | ctx.open_file(f, ro=1, crt=1, read=":xxx:yyy:zzzq") 54 | ctx.open_file(f, ro=1, app=1, crt=1, write="p") 55 | ctx.open_file(f, ro=1, crt=1, read=":xxx:yyy:zzzqp") 56 | -------------------------------------------------------------------------------- /tests/open-plain.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing file; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open read-only 10 | def subtest_1(ctx): 11 | """Open O_RDONLY""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 15 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 16 | 17 | # Open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_WRONLY""" 20 | f = ctx.reg_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, write="q") 23 | ctx.open_file(f, ro=1, read="qxxx:yyy:zzz") 24 | ctx.open_file(f, wo=1, write="p") 25 | ctx.open_file(f, ro=1, read="pxxx:yyy:zzz") 26 | 27 | # Open write-only and append 28 | def subtest_3(ctx): 29 | """Open O_APPEND|O_WRONLY""" 30 | f = ctx.reg_file() + ctx.termslash() 31 | 32 | ctx.open_file(f, app=1, write="q") 33 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzzq") 34 | ctx.open_file(f, app=1, write="p") 35 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzzqp") 36 | 37 | # Open read/write and overwrite 38 | def subtest_4(ctx): 39 | """Open O_RDWR""" 40 | f = ctx.reg_file() + ctx.termslash() 41 | 42 | ctx.open_file(f, rw=1, write="q") 43 | ctx.open_file(f, ro=1, read="qxxx:yyy:zzz") 44 | ctx.open_file(f, rw=1, write="p") 45 | ctx.open_file(f, ro=1, read="pxxx:yyy:zzz") 46 | 47 | # Open read/write and append 48 | def subtest_5(ctx): 49 | """Open O_APPEND|O_RDWR""" 50 | f = ctx.reg_file() + ctx.termslash() 51 | 52 | ctx.open_file(f, ro=1, app=1, write="q") 53 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzzq") 54 | ctx.open_file(f, ro=1, app=1, write="p") 55 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzzqp") 56 | -------------------------------------------------------------------------------- /tests/open-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open of existing file with O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Truncate and open read-only 10 | def subtest_1(ctx): 11 | """Open O_TRUNC|O_RDONLY""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | 14 | ctx.open_file(f, ro=1, tr=1, read="") 15 | ctx.open_file(f, ro=1, tr=1, read="") 16 | 17 | # Truncate, open write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open O_TRUNC|O_WRONLY""" 20 | f = ctx.reg_file() + ctx.termslash() 21 | 22 | ctx.open_file(f, wo=1, tr=1, write="q") 23 | ctx.open_file(f, ro=1, read="q") 24 | ctx.open_file(f, wo=1, tr=1, write="p") 25 | ctx.open_file(f, ro=1, read="p") 26 | 27 | # Truncate, open write-only and append 28 | def subtest_3(ctx): 29 | """Open O_TRUNC|O_APPEND|O_WRONLY""" 30 | f = ctx.reg_file() + ctx.termslash() 31 | 32 | ctx.open_file(f, app=1, tr=1, write="q") 33 | ctx.open_file(f, ro=1, read="q") 34 | ctx.open_file(f, app=1, tr=1, write="p") 35 | ctx.open_file(f, ro=1, read="p") 36 | 37 | # Truncate, open read/write and overwrite 38 | def subtest_4(ctx): 39 | """Open O_TRUNC|O_RDWR""" 40 | f = ctx.reg_file() + ctx.termslash() 41 | 42 | ctx.open_file(f, rw=1, tr=1, write="q") 43 | ctx.open_file(f, ro=1, read="q") 44 | ctx.open_file(f, rw=1, tr=1, write="p") 45 | ctx.open_file(f, ro=1, read="p") 46 | 47 | # Truncate, open read/write and append 48 | def subtest_5(ctx): 49 | """Open O_TRUNC|O_APPEND|O_RDWR""" 50 | f = ctx.reg_file() + ctx.termslash() 51 | 52 | ctx.open_file(f, ro=1, app=1, tr=1, write="q") 53 | ctx.open_file(f, ro=1, read="q") 54 | ctx.open_file(f, ro=1, app=1, tr=1, write="p") 55 | ctx.open_file(f, ro=1, read="p") 56 | -------------------------------------------------------------------------------- /tests/readlink.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Readlink tests 6 | # 7 | ############################################################################### 8 | 9 | def subtest_1(ctx): 10 | """Readlink file""" 11 | f = ctx.reg_file() + ctx.termslash() 12 | 13 | ctx.readlink(f, err=EINVAL) 14 | 15 | def subtest_2(ctx): 16 | """Readlink direct symlink to file""" 17 | f = ctx.direct_sym() + ctx.termslash() 18 | 19 | ctx.readlink(f, content=ctx.direct_sym_val()) 20 | 21 | def subtest_3(ctx): 22 | """Readlink indirect symlink to file""" 23 | f = ctx.indirect_sym() + ctx.termslash() 24 | 25 | ctx.readlink(f, content=ctx.indirect_sym_val()) 26 | 27 | # 28 | # 29 | # 30 | def subtest_4(ctx): 31 | """Readlink dir""" 32 | f = ctx.non_empty_dir() + ctx.termslash() 33 | 34 | ctx.readlink(f, err=EINVAL) 35 | 36 | def subtest_5(ctx): 37 | """Readlink direct symlink to dir""" 38 | f = ctx.direct_dir_sym() + ctx.termslash() 39 | 40 | ctx.readlink(f, content=ctx.direct_dir_sym_val()) 41 | 42 | def subtest_6(ctx): 43 | """Readlink indirect symlink to dir""" 44 | f = ctx.indirect_dir_sym() + ctx.termslash() 45 | 46 | ctx.readlink(f, content=ctx.indirect_dir_sym_val()) 47 | 48 | # 49 | # 50 | # 51 | def subtest_7(ctx): 52 | """Readlink absent file""" 53 | f = ctx.no_file() + ctx.termslash() 54 | 55 | ctx.readlink(f, err=ENOENT) 56 | 57 | def subtest_8(ctx): 58 | """Readlink broken symlink to absent file""" 59 | f = ctx.pointless() + ctx.termslash() 60 | 61 | ctx.readlink(f, content=ctx.pointless_val()) 62 | 63 | def subtest_9(ctx): 64 | """Readlink broken symlink""" 65 | f = ctx.pointless() + ctx.termslash() 66 | 67 | ctx.readlink(f, content=ctx.pointless_val()) 68 | 69 | def subtest_10(ctx): 70 | """Readlink absent file pointed to by broken symlink""" 71 | f = ctx.no_file() + ctx.termslash() 72 | 73 | ctx.readlink(f, err=ENOENT) 74 | -------------------------------------------------------------------------------- /tests/rename-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename populated directories 6 | # 7 | ############################################################################### 8 | 9 | # Rename a populated directory to sibling 10 | def subtest_1(ctx): 11 | """Move populated dir""" 12 | d = ctx.non_empty_dir() + ctx.termslash() 13 | d2 = ctx.empty_dir() + ctx.termslash() + "/x" + ctx.termslash() 14 | 15 | ctx.rename(d, d2) 16 | ctx.rename(d, d2, err=ENOENT) 17 | ctx.open_dir(d2, ro=1) 18 | ctx.open_dir(d, ro=1, err=ENOENT) 19 | ctx.open_file(d2 + "/a", ro=1) 20 | 21 | # Rename a populated directory to sibling parent 22 | def subtest_2(ctx): 23 | """Move populated subdir""" 24 | d = ctx.non_empty_dir() + ctx.termslash() + "/pop" + ctx.termslash() 25 | d2 = ctx.empty_dir() + ctx.termslash() + "/pop" + ctx.termslash() 26 | 27 | ctx.rename(d, d2) 28 | ctx.rename(d, d2, err=ENOENT) 29 | ctx.open_dir(d2, ro=1) 30 | ctx.open_dir(d, ro=1, err=ENOENT) 31 | ctx.open_file(d2 + "/b", ro=1) 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/rename-empty-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename empty directories 6 | # 7 | ############################################################################### 8 | 9 | # Rename an empty directory and rename it back again 10 | def subtest_1(ctx): 11 | """Rename empty dir and rename back""" 12 | d = ctx.empty_dir() + ctx.termslash() 13 | d2 = ctx.no_dir() + ctx.termslash() 14 | 15 | ctx.rename(d, d2) 16 | ctx.rename(d, d2, err=ENOENT) 17 | ctx.rename(d2, d) 18 | ctx.rename(d2, d, err=ENOENT) 19 | ctx.open_dir(d, ro=1) 20 | ctx.open_dir(d2, ro=1, err=ENOENT) 21 | 22 | # Rename an empty directory and remove old name 23 | def subtest_2(ctx): 24 | """Rename empty dir and remove old name""" 25 | d = ctx.empty_dir() + ctx.termslash() 26 | d2 = ctx.no_dir() + ctx.termslash() 27 | 28 | ctx.rename(d, d2) 29 | ctx.rmdir(d, err=ENOENT) 30 | ctx.rename(d2, d) 31 | ctx.rename(d2, d, err=ENOENT) 32 | ctx.open_dir(d, ro=1) 33 | ctx.rmdir(d) 34 | ctx.rmdir(d, err=ENOENT) 35 | ctx.open_dir(d, ro=1, err=ENOENT) 36 | ctx.open_dir(d2, ro=1, err=ENOENT) 37 | 38 | # Rename an empty directory and unlink old name 39 | def subtest_3(ctx): 40 | """Rename empty dir and unlink old name""" 41 | d = ctx.empty_dir() + ctx.termslash() 42 | d2 = ctx.no_dir() + ctx.termslash() 43 | 44 | ctx.rename(d, d2) 45 | ctx.unlink(d, err=ENOENT) 46 | ctx.rename(d2, d) 47 | ctx.rename(d2, d, err=ENOENT) 48 | ctx.open_dir(d, ro=1) 49 | ctx.unlink(d, err=EISDIR) 50 | ctx.open_dir(d, ro=1) 51 | ctx.open_dir(d2, ro=1, err=ENOENT) 52 | 53 | # Remove a directory and rename old name 54 | def subtest_4(ctx): 55 | """Remove dir and rename old name""" 56 | d = ctx.empty_dir() + ctx.termslash() 57 | d2 = ctx.no_dir() + ctx.termslash() 58 | 59 | ctx.rmdir(d) 60 | ctx.rename(d, d2, err=ENOENT) 61 | ctx.rmdir(d, err=ENOENT) 62 | ctx.rmdir(d2, err=ENOENT) 63 | 64 | # Unlink a directory and rename old name 65 | def subtest_5(ctx): 66 | """Unlink dir and rename old name""" 67 | d = ctx.empty_dir() + ctx.termslash() 68 | d2 = ctx.no_dir() + ctx.termslash() 69 | 70 | ctx.unlink(d, err=EISDIR) 71 | ctx.rename(d, d2) 72 | ctx.unlink(d, err=ENOENT) 73 | ctx.rmdir(d2) 74 | 75 | # Rename an empty directory twice 76 | def subtest_6(ctx): 77 | """Rename empty dir twice""" 78 | d = ctx.empty_dir() + ctx.termslash() 79 | d2 = ctx.no_dir() + ctx.termslash() 80 | d3 = ctx.no_dir() + "x" + ctx.termslash() 81 | 82 | ctx.rename(d, d2) 83 | ctx.rename(d, d2, err=ENOENT) 84 | ctx.rename(d2, d3) 85 | ctx.rename(d2, d3, err=ENOENT) 86 | ctx.open_dir(d, ro=1, err=ENOENT) 87 | ctx.open_dir(d2, ro=1, err=ENOENT) 88 | ctx.open_dir(d3, ro=1) 89 | 90 | # Rename an empty directory over another 91 | def subtest_7(ctx): 92 | """Rename empty dir over another populated dir""" 93 | d = ctx.empty_dir() + ctx.termslash() 94 | d2 = ctx.non_empty_dir() + ctx.termslash() 95 | 96 | ctx.rename(d, d2, err=ENOTEMPTY) 97 | ctx.open_dir(d, ro=1) 98 | ctx.open_dir(d2, ro=1) 99 | 100 | # Rename an empty directory over itself 101 | def subtest_8(ctx): 102 | """Rename empty dir over itself""" 103 | d = ctx.empty_dir() + ctx.termslash() 104 | 105 | ctx.rename(d, d) 106 | ctx.open_dir(d, ro=1) 107 | 108 | # Rename an empty directory over a file 109 | def subtest_9(ctx): 110 | """Rename empty dir over a file""" 111 | d = ctx.empty_dir() + ctx.termslash() 112 | f = ctx.reg_file() + ctx.termslash() 113 | f2 = ctx.non_empty_dir() + "/a" + ctx.termslash() 114 | 115 | ctx.rename(d, f, err=ENOTDIR) 116 | ctx.rename(d, f2, err=ENOTDIR) 117 | ctx.open_dir(d, ro=1) 118 | 119 | # Rename an empty directory over the parent dir 120 | def subtest_10(ctx): 121 | """Rename empty dir over parent dir""" 122 | d = ctx.empty_dir() + ctx.termslash() 123 | d2 = ctx.config().testdir() 124 | 125 | ctx.rename(d, d2, err=ENOTEMPTY) 126 | ctx.open_dir(d, ro=1) 127 | -------------------------------------------------------------------------------- /tests/rename-exdev.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename directories expecting EXDEV when REDIRECT_DIR=n 6 | # 7 | ############################################################################### 8 | 9 | # Rename empty directory within same parent 10 | def subtest_1(ctx): 11 | """Rename empty dir within same parent""" 12 | d = ctx.empty_dir() + ctx.termslash() 13 | d2 = ctx.no_dir() + ctx.termslash() 14 | 15 | ctx.rename(d, d2, err=EXDEV) 16 | ctx.open_dir(d2, ro=1, err=ENOENT) 17 | ctx.open_dir(d, ro=1) 18 | 19 | # Move empty directory into another parent 20 | def subtest_2(ctx): 21 | """Move empty dir into another parent""" 22 | d = ctx.empty_dir() 23 | n = d[d.rfind("/"):] 24 | d = d + ctx.termslash() 25 | d2 = ctx.non_empty_dir() + ctx.termslash() + n 26 | 27 | ctx.rename(d, d2, err=EXDEV) 28 | ctx.open_dir(d2, ro=1, err=ENOENT) 29 | ctx.open_dir(d, ro=1) 30 | 31 | # Rename a populated directory within same parent 32 | def subtest_3(ctx): 33 | """Rename populated dir within same parent""" 34 | d = ctx.non_empty_dir() + ctx.termslash() 35 | d2 = ctx.no_dir() + ctx.termslash() 36 | 37 | ctx.rename(d, d2, err=EXDEV) 38 | ctx.open_dir(d2, ro=1, err=ENOENT) 39 | ctx.open_dir(d, ro=1) 40 | ctx.open_file(d2 + "/a", ro=1, err=ENOENT) 41 | ctx.open_file(d + "/a", ro=1) 42 | 43 | # Move a populated directory into another parent 44 | def subtest_4(ctx): 45 | """Move populated dir into another parent""" 46 | d = ctx.non_empty_dir() 47 | n = d[d.rfind("/"):] 48 | d = d + ctx.termslash() 49 | d2 = ctx.empty_dir() + ctx.termslash() + n 50 | 51 | ctx.rename(d, d2, err=EXDEV) 52 | ctx.open_dir(d2, ro=1, err=ENOENT) 53 | ctx.open_dir(d, ro=1) 54 | ctx.open_file(d2 + "/a", ro=1, err=ENOENT) 55 | ctx.open_file(d + "/a", ro=1) 56 | -------------------------------------------------------------------------------- /tests/rename-file.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename files 6 | # 7 | ############################################################################### 8 | 9 | # Rename a file and rename it back again 10 | def subtest_1(ctx): 11 | """Rename file and rename back""" 12 | f = ctx.reg_file() + ctx.termslash() 13 | f2 = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.rename(f, f2) 16 | ctx.rename(f, f2, err=ENOENT) 17 | ctx.rename(f2, f) 18 | ctx.rename(f2, f, err=ENOENT) 19 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 20 | ctx.open_file(f2, ro=1, err=ENOENT) 21 | 22 | # Rename a file and unlink old name 23 | def subtest_2(ctx): 24 | """Rename file and unlink old name""" 25 | f = ctx.reg_file() + ctx.termslash() 26 | f2 = ctx.no_file() + ctx.termslash() 27 | 28 | ctx.rename(f, f2) 29 | ctx.unlink(f, err=ENOENT) 30 | ctx.rename(f2, f) 31 | ctx.rename(f2, f, err=ENOENT) 32 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 33 | ctx.unlink(f) 34 | ctx.unlink(f, err=ENOENT) 35 | ctx.open_file(f, ro=1, err=ENOENT) 36 | ctx.open_file(f2, ro=1, err=ENOENT) 37 | 38 | # Rename a file and rmdir old name 39 | def subtest_3(ctx): 40 | """Rename file and rmdir old name""" 41 | f = ctx.reg_file() + ctx.termslash() 42 | f2 = ctx.no_file() + ctx.termslash() 43 | 44 | ctx.rename(f, f2) 45 | ctx.rmdir(f, err=ENOENT) 46 | ctx.rename(f2, f) 47 | ctx.rename(f2, f, err=ENOENT) 48 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 49 | ctx.rmdir(f, err=ENOTDIR) 50 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 51 | ctx.open_file(f2, ro=1, err=ENOENT) 52 | 53 | # Unlink a file and rename old name 54 | def subtest_4(ctx): 55 | """Unlink file and rename old name""" 56 | f = ctx.reg_file() + ctx.termslash() 57 | f2 = ctx.no_file() + ctx.termslash() 58 | 59 | ctx.unlink(f) 60 | ctx.rename(f, f2, err=ENOENT) 61 | ctx.unlink(f, err=ENOENT) 62 | ctx.unlink(f2, err=ENOENT) 63 | 64 | # Rmdir a file and rename old name 65 | def subtest_5(ctx): 66 | """Rmdir file and rename old name""" 67 | f = ctx.reg_file() + ctx.termslash() 68 | f2 = ctx.no_file() + ctx.termslash() 69 | 70 | ctx.rmdir(f, err=ENOTDIR) 71 | ctx.rename(f, f2) 72 | ctx.rmdir(f, err=ENOENT) 73 | ctx.unlink(f2) 74 | 75 | # Rename a file twice 76 | def subtest_6(ctx): 77 | """Rename file twice""" 78 | f = ctx.reg_file() + ctx.termslash() 79 | f2 = ctx.no_file() + ctx.termslash() 80 | f3 = ctx.no_file() + "x" + ctx.termslash() 81 | 82 | ctx.rename(f, f2) 83 | ctx.rename(f, f2, err=ENOENT) 84 | ctx.rename(f2, f3) 85 | ctx.rename(f2, f3, err=ENOENT) 86 | ctx.open_file(f, ro=1, err=ENOENT) 87 | ctx.open_file(f2, ro=1, err=ENOENT) 88 | ctx.open_file(f3, ro=1, read=":xxx:yyy:zzz") 89 | 90 | # Rename a file over another 91 | def subtest_7(ctx): 92 | """Rename file over another""" 93 | f = ctx.reg_file() + ctx.termslash() 94 | f2 = ctx.non_empty_dir() + "/a" + ctx.termslash() 95 | 96 | ctx.rename(f, f2) 97 | ctx.rename(f, f2, err=ENOENT) 98 | ctx.open_file(f, ro=1, err=ENOENT) 99 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 100 | 101 | # Rename a file over itself 102 | def subtest_8(ctx): 103 | """Rename file over itself""" 104 | f = ctx.reg_file() + ctx.termslash() 105 | 106 | ctx.rename(f, f) 107 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 108 | 109 | # Rename a file over a directory 110 | def subtest_9(ctx): 111 | """Rename file over a dir""" 112 | f = ctx.reg_file() + ctx.termslash() 113 | d = ctx.empty_dir() + ctx.termslash() 114 | d2 = ctx.non_empty_dir() + ctx.termslash() 115 | 116 | ctx.rename(f, d, err=EISDIR) 117 | ctx.rename(f, d2, err=EISDIR) 118 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 119 | 120 | # Rename a file over the parent dir 121 | def subtest_10(ctx): 122 | """Rename file over parent dir""" 123 | f = ctx.reg_file() + ctx.termslash() 124 | d = ctx.config().testdir() 125 | 126 | ctx.rename(f, d, err=ENOTEMPTY) 127 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 128 | -------------------------------------------------------------------------------- /tests/rename-hard-link.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename hardlinked files 6 | # 7 | ############################################################################### 8 | 9 | def subtest_1(ctx): 10 | """Rename hardlinked file""" 11 | f = ctx.reg_file() + ctx.termslash() 12 | f2 = ctx.no_file() + ctx.termslash() 13 | f3 = ctx.no_file() + "-a" + ctx.termslash() 14 | f4 = ctx.reg_file() + "-a" + ctx.termslash() 15 | 16 | ctx.link(f, f2) 17 | ctx.rename(f2, f3) 18 | ctx.rename(f3, f2) 19 | ctx.rename(f, f4) 20 | 21 | ctx.open_file(f, ro=1, err=ENOENT) 22 | ctx.open_file(f2, ro=1, read=":xxx:yyy:zzz") 23 | ctx.open_file(f3, ro=1, err=ENOENT) 24 | ctx.open_file(f4, ro=1, read=":xxx:yyy:zzz") 25 | -------------------------------------------------------------------------------- /tests/rename-mass-2.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of files 6 | # 7 | ############################################################################### 8 | 9 | file_count = 104 10 | iter_count = 3 11 | 12 | # Mass rename a bunch of files, where N is the file number, through 13 | # fooN_0...fooN_M, where M is the number of iterations 14 | def subtest_1(ctx): 15 | """Mass rename fooN_0->fooN_1->...->fooN_M""" 16 | base = ctx.reg_file()[:-3] 17 | 18 | for i in range(100, file_count): 19 | path = base + "{:d}".format(i) 20 | path2 = path + "_0" 21 | ctx.rename(path, path2) 22 | 23 | for j in range(0, iter_count): 24 | for i in range(file_count - 1, 100 - 1, -1): 25 | path = base + "{:d}_{:d}".format(i, j) 26 | path2 = base + "{:d}_{:d}".format(i, j + 1) 27 | ctx.rename(path, path2) 28 | 29 | # Delete the previously mass renamed files 30 | def subtest_2(ctx): 31 | """Unlink mass renamed files""" 32 | base = ctx.reg_file()[:-3] 33 | 34 | for i in range(100, file_count): 35 | path = base + "{:d}_{:d}".format(i, iter_count) 36 | ctx.unlink(path) 37 | -------------------------------------------------------------------------------- /tests/rename-mass-3.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of files 6 | # 7 | ############################################################################### 8 | 9 | ring_size = 7 10 | iter_count = int(ring_size * 4.5) 11 | 12 | # Mass rename a bunch of sequentially-named files, through a circular 13 | # set of names, leaving a gap to move into. The files are named 14 | # 0...ring_size-2 and the gap starts at ring_size-1 and moves backwards. 15 | # 16 | def subtest_1(ctx): 17 | """Mass rename sequential files circularly""" 18 | base = ctx.reg_file()[:-3] 19 | 20 | gap = ring_size - 1 21 | for i in range(0, iter_count): 22 | next_gap = (gap - 1) % ring_size 23 | path = base + "{:d}".format(100 + next_gap) 24 | path2 = base + "{:d}".format(100 + gap) 25 | ctx.rename(path, path2) 26 | gap = next_gap 27 | 28 | # Delete the previously mass renamed files 29 | def subtest_2(ctx): 30 | """Unlink mass renamed files""" 31 | base = ctx.reg_file()[:-3] 32 | 33 | gap = -(iter_count + 1) % ring_size 34 | for i in range(0, ring_size): 35 | path = base + "{:d}".format(100 + i) 36 | if i == gap: 37 | ctx.unlink(path, err=ENOENT) 38 | else: 39 | ctx.unlink(path) 40 | -------------------------------------------------------------------------------- /tests/rename-mass-4.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of files 6 | # 7 | ############################################################################### 8 | 9 | ring_size = 7 10 | iter_count = int(ring_size * 4.5) 11 | 12 | # Mass create a bunch of sequentially-named files, and then rename through a 13 | # circular set of names, leaving a gap to move into. The files are named 14 | # 0...ring_size-2 and the gap starts at ring_size-1 and moves backwards. 15 | # 16 | def subtest_1(ctx): 17 | """Mass rename new sequential files circularly""" 18 | base = ctx.no_file()[:-3] 19 | 20 | for i in range(0, ring_size): 21 | path = base + "{:d}".format(100 + i) 22 | ctx.open_file(path, wo=1, crt=1, write="abcd{:d}".format(i)) 23 | 24 | gap = ring_size - 1 25 | for i in range(0, iter_count): 26 | next_gap = (gap - 1) % ring_size 27 | path = base + "{:d}".format(100 + next_gap) 28 | path2 = base + "{:d}".format(100 + gap) 29 | ctx.rename(path, path2) 30 | gap = next_gap 31 | 32 | # Delete the previously mass renamed files 33 | def subtest_2(ctx): 34 | """Unlink mass renamed files""" 35 | base = ctx.no_file()[:-3] 36 | 37 | gap = -(iter_count + 1) % ring_size 38 | for i in range(0, ring_size): 39 | path = base + "{:d}".format(100 + i) 40 | if i == gap: 41 | ctx.unlink(path, err=ENOENT) 42 | else: 43 | ctx.unlink(path) 44 | -------------------------------------------------------------------------------- /tests/rename-mass-5.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of files 6 | # 7 | ############################################################################### 8 | 9 | ring_size = 7 10 | iter_count = int(ring_size * 4.5) 11 | 12 | # Mass hardlink a bunch of sequentially-named files, and then rename through a 13 | # circular set of names, leaving a gap to move into. The files are named 14 | # 0...ring_size-2 and the gap starts at ring_size-1 and moves backwards. 15 | # 16 | def subtest_1(ctx): 17 | """Mass rename hardlinked sequential files circularly""" 18 | src_base = ctx.reg_file()[:-3] 19 | base = ctx.no_file()[:-3] 20 | 21 | for i in range(0, ring_size + 1): 22 | src = src_base + "{:d}".format(100 + i) 23 | path = base + "{:d}".format(100 + i) 24 | ctx.link(src, path) 25 | 26 | gap = ring_size - 1 27 | for i in range(0, iter_count): 28 | next_gap = (gap - 1) % ring_size 29 | path = base + "{:d}".format(100 + next_gap) 30 | path2 = base + "{:d}".format(100 + gap) 31 | ctx.rename(path, path2) 32 | gap = next_gap 33 | 34 | gap = ring_size - 1 35 | for i in range(0, iter_count): 36 | next_gap = (gap + 1) % ring_size 37 | path = src_base + "{:d}".format(100 + next_gap) 38 | path2 = src_base + "{:d}".format(100 + gap) 39 | ctx.rename(path, path2) 40 | gap = next_gap 41 | 42 | # Delete the previously mass renamed files 43 | def subtest_2(ctx): 44 | """Unlink mass renamed files""" 45 | src_base = ctx.reg_file()[:-3] 46 | base = ctx.no_file()[:-3] 47 | 48 | gap = -(iter_count + 1) % ring_size 49 | for i in range(0, ring_size + 1): 50 | path = base + "{:d}".format(100 + i) 51 | if i == gap: 52 | ctx.unlink(path, err=ENOENT) 53 | else: 54 | ctx.unlink(path) 55 | 56 | gap = (iter_count - 1) % ring_size 57 | for i in range(0, ring_size + 1): 58 | src = src_base + "{:d}".format(100 + i) 59 | if i == gap: 60 | ctx.unlink(src, err=ENOENT) 61 | else: 62 | ctx.unlink(src) 63 | -------------------------------------------------------------------------------- /tests/rename-mass-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of directories 6 | # 7 | ############################################################################### 8 | 9 | ring_size = 7 10 | iter_count = int(ring_size * 4.5) 11 | 12 | # Mass create a bunch of sequentially-named directories, and then rename 13 | # through a circular set of names, leaving a gap to move into. The dirs are 14 | # named 0...ring_size-2 and the gap starts at ring_size-1 and moves backwards. 15 | # 16 | def subtest_1(ctx): 17 | """Mass rename new sequential dirs circularly""" 18 | base = ctx.no_dir()[:-3] 19 | 20 | for i in range(0, ring_size - 1): 21 | path = base + "{:d}".format(100 + i) 22 | ctx.mkdir(path, 0o755) 23 | 24 | gap = ring_size - 1 25 | for i in range(0, iter_count): 26 | next_gap = (gap - 1) % ring_size 27 | path = base + "{:d}".format(100 + next_gap) 28 | path2 = base + "{:d}".format(100 + gap) 29 | ctx.rename(path, path2) 30 | gap = next_gap 31 | 32 | # Delete the previously mass renamed directories 33 | def subtest_2(ctx): 34 | """Unlink mass renamed dirs""" 35 | base = ctx.no_dir()[:-3] 36 | 37 | gap = -(iter_count + 1) % ring_size 38 | for i in range(0, ring_size): 39 | path = base + "{:d}".format(100 + i) 40 | if i == gap: 41 | ctx.rmdir(path, err=ENOENT) 42 | else: 43 | ctx.rmdir(path) 44 | 45 | # As before, but with populated directories 46 | def subtest_3(ctx): 47 | """Mass rename new populated sequential dirs circularly""" 48 | base = ctx.no_dir()[:-3] 49 | 50 | for i in range(0, ring_size - 1): 51 | path = base + "{:d}".format(100 + i) 52 | ctx.mkdir(path, 0o755) 53 | ctx.open_file(path + "/a", wo=1, crt=1, write="abcd{:d}".format(i)) 54 | 55 | gap = ring_size - 1 56 | for i in range(0, iter_count): 57 | next_gap = (gap - 1) % ring_size 58 | path = base + "{:d}".format(100 + next_gap) 59 | path2 = base + "{:d}".format(100 + gap) 60 | ctx.rename(path, path2) 61 | gap = next_gap 62 | 63 | # Read the files in the previously mass-renamed directories 64 | def subtest_4(ctx): 65 | """Check files in renamed dirs""" 66 | base = ctx.no_dir()[:-3] 67 | 68 | # The cycle repeats itself after R * (R-1) iterations 69 | n = iter_count % (ring_size * (ring_size - 1)) 70 | 71 | # The gap is back at the end every R iterations 72 | cycle = int(n / ring_size) 73 | 74 | # Thus the first number in the sequence in this cycle is... 75 | n = (ring_size - 1) - cycle 76 | 77 | gap = -(iter_count + 1) % ring_size 78 | for i in range(0, ring_size): 79 | if i == gap: 80 | pass 81 | else: 82 | path = base + "{:d}".format(100 + i) 83 | ctx.open_file(path + "/a", ro=1, read="abcd{:d}".format(n)) 84 | n = (n + 1) % (ring_size - 1) 85 | 86 | # Delete the previously mass-renamed directories 87 | def subtest_5(ctx): 88 | """Unlink mass renamed dirs""" 89 | base = ctx.no_dir()[:-3] 90 | 91 | gap = -(iter_count + 1) % ring_size 92 | for i in range(0, ring_size): 93 | path = base + "{:d}".format(100 + i) 94 | if i == gap: 95 | ctx.rmdir(path, err=ENOENT) 96 | else: 97 | ctx.unlink(path + "/a") 98 | ctx.rmdir(path) 99 | -------------------------------------------------------------------------------- /tests/rename-mass-sym.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of symlinks 6 | # 7 | ############################################################################### 8 | 9 | ring_size = 7 10 | iter_count = int(ring_size * 4.5) 11 | 12 | # Mass rename a bunch of sequentially-named symlinks through a circular set of 13 | # names, leaving a gap to move into. The symlinks are named 0...ring_size-2 14 | # and the gap starts at ring_size-1 and moves backwards. 15 | # 16 | def subtest_1(ctx): 17 | """Mass rename sequential symlinks circularly""" 18 | base = ctx.direct_sym()[:-3] 19 | 20 | gap = ring_size - 1 21 | for i in range(0, iter_count): 22 | next_gap = (gap - 1) % ring_size 23 | path = base + "{:d}".format(100 + next_gap) 24 | path2 = base + "{:d}".format(100 + gap) 25 | ctx.rename(path, path2) 26 | gap = next_gap 27 | 28 | # Read the previously mass-renamed symlinks 29 | def subtest_2(ctx): 30 | """Check renamed symlink contents""" 31 | base = ctx.direct_sym()[:-3] 32 | 33 | # The cycle repeats itself after R * (R-1) iterations 34 | n = iter_count % (ring_size * (ring_size - 1)) 35 | 36 | # The gap is back at the end every R iterations 37 | cycle = int(n / ring_size) 38 | 39 | # Thus the first number in the sequence in this cycle is... 40 | n = (ring_size - 1) - cycle 41 | 42 | gap = -(iter_count + 1) % ring_size 43 | for i in range(0, ring_size): 44 | if i == gap: 45 | pass 46 | else: 47 | path = base + "{:d}".format(100 + i) 48 | ctx.readlink(path, content="../a/foo{:d}".format(100 + n)) 49 | ctx.open_file(path, ro=1, read=":xxx:yyy:zzz") 50 | n = (n + 1) % (ring_size - 1) 51 | 52 | # Delete the previously mass-renamed symlinks 53 | def subtest_3(ctx): 54 | """Unlink mass renamed symlinks""" 55 | base = ctx.direct_sym()[:-3] 56 | 57 | gap = -(iter_count + 1) % ring_size 58 | for i in range(0, ring_size + 1): 59 | path = base + "{:d}".format(100 + i) 60 | if i == gap: 61 | ctx.unlink(path, err=ENOENT) 62 | else: 63 | ctx.unlink(path) 64 | 65 | # As above, but using symlinks to dirs 66 | def subtest_4(ctx): 67 | """Mass rename sequential dir symlinks circularly""" 68 | base = ctx.direct_dir_sym()[:-3] 69 | 70 | gap = ring_size - 1 71 | for i in range(0, iter_count): 72 | next_gap = (gap - 1) % ring_size 73 | path = base + "{:d}".format(100 + next_gap) 74 | path2 = base + "{:d}".format(100 + gap) 75 | ctx.rename(path, path2) 76 | gap = next_gap 77 | 78 | # Read the previously mass-renamed symlinks 79 | def subtest_5(ctx): 80 | """Check renamed symlink contents""" 81 | base = ctx.direct_dir_sym()[:-3] 82 | 83 | # The cycle repeats itself after R * (R-1) iterations 84 | n = iter_count % (ring_size * (ring_size - 1)) 85 | 86 | # The gap is back at the end every R iterations 87 | cycle = int(n / ring_size) 88 | 89 | # Thus the first number in the sequence in this cycle is... 90 | n = (ring_size - 1) - cycle 91 | 92 | gap = -(iter_count + 1) % ring_size 93 | for i in range(0, ring_size): 94 | if i == gap: 95 | pass 96 | else: 97 | path = base + "{:d}".format(100 + i) 98 | ctx.readlink(path, content="../a/dir{:d}".format(100 + n)) 99 | ctx.open_dir(path, ro=1) 100 | n = (n + 1) % (ring_size - 1) 101 | 102 | # Delete the previously mass-renamed symlinks 103 | def subtest_6(ctx): 104 | """Unlink mass renamed symlinks""" 105 | base = ctx.direct_dir_sym()[:-3] 106 | 107 | gap = -(iter_count + 1) % ring_size 108 | for i in range(0, ring_size + 1): 109 | path = base + "{:d}".format(100 + i) 110 | if i == gap: 111 | ctx.unlink(path, err=ENOENT) 112 | else: 113 | ctx.rmdir(path, err=ENOTDIR) 114 | ctx.unlink(path) 115 | -------------------------------------------------------------------------------- /tests/rename-mass.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Mass rename of files 6 | # 7 | ############################################################################### 8 | 9 | file_count = 104 10 | iter_count = 3 11 | 12 | # Mass rename a bunch of sequentially-named files, where each file in the 13 | # sequence is moved up one, starting from the highest, such that each file is 14 | # renamed to where its successor just was. 15 | def subtest_1(ctx): 16 | """Mass rename sequential files into each other's vacated name slots""" 17 | base = ctx.reg_file()[:-3] 18 | 19 | for j in range(0, iter_count): 20 | for i in range(file_count - 1, 100 - 1, -1): 21 | path = base + "{:d}".format(i + j) 22 | path2 = base + "{:d}".format(i + j + 1) 23 | ctx.rename(path, path2) 24 | 25 | # Delete the previously mass renamed files 26 | def subtest_2(ctx): 27 | """Unlink mass renamed files""" 28 | base = ctx.reg_file()[:-3] 29 | 30 | for i in range(100, file_count): 31 | path = base + "{:d}".format(i + iter_count) 32 | ctx.unlink(path) 33 | -------------------------------------------------------------------------------- /tests/rename-move-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to move directories 6 | # 7 | ############################################################################### 8 | 9 | # Move empty directory into another 10 | def subtest_1(ctx): 11 | """Move empty dir into another""" 12 | d = ctx.empty_dir() 13 | n = d[d.rfind("/"):] 14 | d = d + ctx.termslash() 15 | d2 = ctx.non_empty_dir() + ctx.termslash() + n 16 | 17 | ctx.rename(d, d2) 18 | ctx.rename(d, d2, err=ENOENT) 19 | ctx.open_dir(d2, ro=1) 20 | ctx.open_dir(d, ro=1, err=ENOENT) 21 | 22 | # Move a populated directory into another 23 | def subtest_2(ctx): 24 | """Move populated dir into another""" 25 | d = ctx.non_empty_dir() 26 | n = d[d.rfind("/"):] 27 | d = d + ctx.termslash() 28 | d2 = ctx.empty_dir() + ctx.termslash() + n 29 | 30 | ctx.rename(d, d2) 31 | ctx.rename(d, d2, err=ENOENT) 32 | ctx.open_dir(d2, ro=1) 33 | ctx.open_dir(d, ro=1, err=ENOENT) 34 | ctx.open_file(d2 + "/a", ro=1) 35 | 36 | # Move a populated directory into another after rename in origin dir 37 | def subtest_3(ctx): 38 | """Rename populated dir and move into another""" 39 | d = ctx.non_empty_dir() 40 | n = d[d.rfind("/"):] 41 | d2 = d + "x" + ctx.termslash() 42 | d = d + ctx.termslash() 43 | d3 = ctx.empty_dir() + ctx.termslash() + n 44 | 45 | ctx.rename(d, d2) 46 | ctx.rename(d, d2, err=ENOENT) 47 | ctx.rename(d2, d3) 48 | ctx.rename(d2, d3, err=ENOENT) 49 | ctx.open_dir(d, ro=1, err=ENOENT) 50 | ctx.open_dir(d2, ro=1, err=ENOENT) 51 | ctx.open_dir(d3, ro=1) 52 | ctx.open_file(d3 + "/a", ro=1) 53 | 54 | # Move a populated directory into another and rename in other dir 55 | def subtest_4(ctx): 56 | """Move populated dir into another and rename""" 57 | d = ctx.non_empty_dir() 58 | n = d[d.rfind("/"):] 59 | d = d + ctx.termslash() 60 | d2 = ctx.empty_dir() + ctx.termslash() + n 61 | d3 = ctx.empty_dir() + ctx.termslash() + n + "x" 62 | 63 | ctx.rename(d, d2) 64 | ctx.rename(d, d2, err=ENOENT) 65 | ctx.rename(d2, d3) 66 | ctx.rename(d2, d3, err=ENOENT) 67 | ctx.open_dir(d, ro=1, err=ENOENT) 68 | ctx.open_dir(d2, ro=1, err=ENOENT) 69 | ctx.open_dir(d3, ro=1) 70 | ctx.open_file(d3 + "/a", ro=1) 71 | 72 | # Move a populated dir into another and move dir inside it to another 73 | def subtest_5(ctx): 74 | """Move populated dir into another and move subdir into another""" 75 | d = ctx.non_empty_dir() 76 | n = d[d.rfind("/"):] 77 | d = d + ctx.termslash() 78 | d2 = ctx.empty_dir() + ctx.termslash() + n 79 | d2a = d2 + "/pop" 80 | d3 = ctx.empty_dir() + "/pop" 81 | 82 | ctx.rename(d, d2) 83 | ctx.rename(d, d2, err=ENOENT) 84 | ctx.rename(d2a, d3) 85 | ctx.rename(d2a, d3, err=ENOENT) 86 | 87 | ctx.open_dir(d, ro=1, err=ENOENT) 88 | ctx.open_dir(d2, ro=1) 89 | ctx.open_dir(d2a, ro=1, err=ENOENT) 90 | ctx.open_dir(d3, ro=1) 91 | ctx.open_file(d2 + "/a", ro=1) 92 | ctx.open_file(d3 + "/b", ro=1) 93 | 94 | # Move a populated directory into another after rename self and child 95 | def subtest_6(ctx): 96 | """Rename populated dir and child and move into another""" 97 | d = ctx.non_empty_dir() 98 | n = d[d.rfind("/"):] 99 | d2 = d + "x" + ctx.termslash() 100 | d2a = d2 + "/pop" 101 | d = d + ctx.termslash() 102 | da = d + "/pop" 103 | db = d + "/popx" 104 | d3 = ctx.empty_dir() + ctx.termslash() + n 105 | d3a = d3 + "/pop" 106 | d3b = d3 + "/popx" 107 | 108 | ctx.rename(da, db, recycle=False) 109 | ctx.rename(da, db, err=ENOENT) 110 | ctx.rename(d, d2) 111 | ctx.rename(d, d2, err=ENOENT) 112 | ctx.rename(d2, d3) 113 | ctx.rename(d2, d3, err=ENOENT) 114 | ctx.open_dir(d, ro=1, err=ENOENT) 115 | ctx.open_dir(d2, ro=1, err=ENOENT) 116 | ctx.open_dir(d3, ro=1) 117 | ctx.open_dir(d3a, ro=1, err=ENOENT) 118 | ctx.open_dir(d3b, ro=1) 119 | ctx.open_file(d3 + "/a", ro=1) 120 | ctx.open_file(d3b + "/b", ro=1) 121 | 122 | # Move a populated directory into another after rename self and parent 123 | def subtest_7(ctx): 124 | """Rename populated dir and parent and move into another""" 125 | d = ctx.non_empty_dir() 126 | n = d[d.rfind("/"):] 127 | d2 = d + "x" + ctx.termslash() 128 | d2a = d2 + "/pop" 129 | d2b = d2 + "/popx" 130 | d = d + ctx.termslash() 131 | da = d + "/pop" 132 | db = d + "/popx" 133 | d3 = ctx.empty_dir() + ctx.termslash() 134 | d3a = d3 + "/pop" 135 | d3b = d3 + "/popx" 136 | 137 | ctx.rename(da, db, recycle=False) 138 | ctx.rename(da, db, err=ENOENT) 139 | ctx.rename(d, d2) 140 | ctx.rename(d, d2, err=ENOENT) 141 | ctx.rename(d2b, d3b) 142 | ctx.rename(d2b, d3b, err=ENOENT) 143 | ctx.open_dir(d, ro=1, err=ENOENT) 144 | ctx.open_dir(d2, ro=1) 145 | ctx.open_dir(d2a, ro=1, err=ENOENT) 146 | ctx.open_dir(d2b, ro=1, err=ENOENT) 147 | ctx.open_dir(d3, ro=1) 148 | ctx.open_dir(d3a, ro=1, err=ENOENT) 149 | ctx.open_dir(d3b, ro=1) 150 | ctx.open_file(d2 + "/a", ro=1) 151 | ctx.open_file(d3b + "/b", ro=1) 152 | 153 | # Move a new empty directory into an empty lower dir 154 | def subtest_8(ctx): 155 | """Move new empty dir into empty lower""" 156 | d = ctx.empty_dir() + "-new" + ctx.termslash() 157 | d2 = ctx.empty_dir() + "/new" + ctx.termslash() 158 | 159 | ctx.mkdir(d, 0o755) 160 | ctx.rename(d, d2) 161 | ctx.open_dir(d, ro=1, err=ENOENT) 162 | ctx.open_dir(d2, ro=1) 163 | 164 | # Move a new empty directory into lower ancestor 165 | def subtest_9(ctx): 166 | """Move new empty dir into lower ancestor""" 167 | d = ctx.empty_dir() + "/new" + ctx.termslash() 168 | d2 = ctx.no_dir() + ctx.termslash() 169 | 170 | ctx.mkdir(d, 0o755) 171 | ctx.rename(d, d2) 172 | ctx.open_dir(d, ro=1, err=ENOENT) 173 | ctx.open_dir(d2, ro=1) 174 | 175 | # Move a new directory leaf into lower ancestor 176 | def subtest_10(ctx): 177 | """Move new dir leaf into lower ancestor""" 178 | p = ctx.empty_dir() + "/newp" 179 | d = p + "/new" + ctx.termslash() 180 | d2 = ctx.no_dir() + ctx.termslash() 181 | 182 | ctx.mkdir(p, 0o755) 183 | ctx.mkdir(d, 0o755) 184 | ctx.rename(d, d2) 185 | ctx.open_dir(d, ro=1, err=ENOENT) 186 | ctx.open_dir(d2, ro=1) 187 | 188 | # Move a new directory branch into lower ancestor 189 | def subtest_11(ctx): 190 | """Move new dir branch into lower ancestor""" 191 | p = ctx.empty_dir() + "/newp" 192 | d = p + "/new" + ctx.termslash() 193 | n = ctx.no_dir() 194 | d2 = n + ctx.termslash() 195 | 196 | ctx.mkdir(p, 0o755) 197 | ctx.mkdir(d, 0o755) 198 | ctx.rename(p, d2) 199 | ctx.open_dir(p, ro=1, err=ENOENT) 200 | ctx.open_dir(d, ro=1, err=ENOENT) 201 | ctx.open_dir(d2, ro=1) 202 | ctx.open_dir(n + "/new", ro=1) 203 | 204 | # Move a populated directory into a new dir 205 | def subtest_12(ctx): 206 | """Move populated dir into a new dir""" 207 | d = ctx.non_empty_dir() 208 | n = d[d.rfind("/"):] 209 | d = d + ctx.termslash() 210 | p = ctx.empty_dir() + "/new" + ctx.termslash() 211 | d2 = p + n + ctx.termslash() 212 | 213 | ctx.mkdir(p, 0o755) 214 | ctx.rename(d, d2) 215 | ctx.rename(d, d2, err=ENOENT) 216 | ctx.open_dir(d2, ro=1) 217 | ctx.open_dir(d, ro=1, err=ENOENT) 218 | ctx.open_file(d2 + "/a", ro=1) 219 | -------------------------------------------------------------------------------- /tests/rename-new-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename empty new directories 6 | # 7 | ############################################################################### 8 | 9 | # Rename an empty directory and rename it back again 10 | def subtest_1(ctx): 11 | """Rename new empty dir and rename back""" 12 | d = ctx.empty_dir() + "-new" + ctx.termslash() 13 | d2 = ctx.no_dir() + ctx.termslash() 14 | 15 | ctx.mkdir(d, 0o755) 16 | ctx.rename(d, d2) 17 | ctx.rename(d, d2, err=ENOENT) 18 | ctx.rename(d2, d) 19 | ctx.rename(d2, d, err=ENOENT) 20 | ctx.open_dir(d, ro=1) 21 | ctx.open_dir(d2, ro=1, err=ENOENT) 22 | 23 | # Rename an empty directory and remove old name 24 | def subtest_2(ctx): 25 | """Rename new empty dir and remove old name""" 26 | d = ctx.empty_dir() + "-new" + ctx.termslash() 27 | d2 = ctx.no_dir() + ctx.termslash() 28 | 29 | ctx.mkdir(d, 0o755) 30 | ctx.rename(d, d2) 31 | ctx.rmdir(d, err=ENOENT) 32 | ctx.rename(d2, d) 33 | ctx.rename(d2, d, err=ENOENT) 34 | ctx.open_dir(d, ro=1) 35 | ctx.rmdir(d) 36 | ctx.rmdir(d, err=ENOENT) 37 | ctx.open_dir(d, ro=1, err=ENOENT) 38 | ctx.open_dir(d2, ro=1, err=ENOENT) 39 | 40 | # Rename an empty directory and unlink old name 41 | def subtest_3(ctx): 42 | """Rename new empty dir and unlink old name""" 43 | d = ctx.empty_dir() + "-new" + ctx.termslash() 44 | d2 = ctx.no_dir() + ctx.termslash() 45 | 46 | ctx.mkdir(d, 0o755) 47 | ctx.rename(d, d2) 48 | ctx.unlink(d, err=ENOENT) 49 | ctx.rename(d2, d) 50 | ctx.rename(d2, d, err=ENOENT) 51 | ctx.open_dir(d, ro=1) 52 | ctx.unlink(d, err=EISDIR) 53 | ctx.open_dir(d, ro=1) 54 | ctx.open_dir(d2, ro=1, err=ENOENT) 55 | 56 | # Remove a directory and rename old name 57 | def subtest_4(ctx): 58 | """Remove new empty dir and rename old name""" 59 | d = ctx.empty_dir() + "-new" + ctx.termslash() 60 | d2 = ctx.no_dir() + ctx.termslash() 61 | 62 | ctx.mkdir(d, 0o755) 63 | ctx.rmdir(d) 64 | ctx.rename(d, d2, err=ENOENT) 65 | ctx.rmdir(d, err=ENOENT) 66 | ctx.rmdir(d2, err=ENOENT) 67 | 68 | # Unlink a directory and rename old name 69 | def subtest_5(ctx): 70 | """Unlink new empty dir and rename old name""" 71 | d = ctx.empty_dir() + "-new" + ctx.termslash() 72 | d2 = ctx.no_dir() + ctx.termslash() 73 | 74 | ctx.mkdir(d, 0o755) 75 | ctx.unlink(d, err=EISDIR) 76 | ctx.rename(d, d2) 77 | ctx.unlink(d, err=ENOENT) 78 | ctx.rmdir(d2) 79 | 80 | # Rename an empty directory twice 81 | def subtest_6(ctx): 82 | """Rename new empty dir twice""" 83 | d = ctx.empty_dir() + "-new" + ctx.termslash() 84 | d2 = ctx.no_dir() + ctx.termslash() 85 | d3 = ctx.no_dir() + "x" + ctx.termslash() 86 | 87 | ctx.mkdir(d, 0o755) 88 | ctx.rename(d, d2) 89 | ctx.rename(d, d2, err=ENOENT) 90 | ctx.rename(d2, d3) 91 | ctx.rename(d2, d3, err=ENOENT) 92 | ctx.open_dir(d2, ro=1, err=ENOENT) 93 | ctx.open_dir(d2, ro=1, err=ENOENT) 94 | ctx.open_dir(d3, ro=1) 95 | 96 | # Rename an empty directory over another 97 | def subtest_7(ctx): 98 | """Rename new empty dir over another populated dir""" 99 | d = ctx.empty_dir() + "-new" + ctx.termslash() 100 | d2 = ctx.non_empty_dir() + ctx.termslash() 101 | 102 | ctx.mkdir(d, 0o755) 103 | ctx.rename(d, d2, err=ENOTEMPTY) 104 | ctx.open_dir(d, ro=1) 105 | ctx.open_dir(d2, ro=1) 106 | 107 | # Rename an empty directory over itself 108 | def subtest_8(ctx): 109 | """Rename new empty dir over itself""" 110 | d = ctx.empty_dir() + "-new" + ctx.termslash() 111 | 112 | ctx.mkdir(d, 0o755) 113 | ctx.rename(d, d) 114 | ctx.open_dir(d, ro=1) 115 | 116 | # Rename an empty directory over a file 117 | def subtest_9(ctx): 118 | """Rename new empty dir over a file""" 119 | d = ctx.empty_dir() + "-new" + ctx.termslash() 120 | f = ctx.reg_file() + ctx.termslash() 121 | f2 = ctx.non_empty_dir() + "/a" + ctx.termslash() 122 | 123 | ctx.mkdir(d, 0o755) 124 | ctx.rename(d, f, err=ENOTDIR) 125 | ctx.rename(d, f2, err=ENOTDIR) 126 | ctx.open_dir(d, ro=1) 127 | 128 | # Rename an empty directory over the parent dir 129 | def subtest_10(ctx): 130 | """Rename new empty dir over parent dir""" 131 | d = ctx.empty_dir() + "-new" + ctx.termslash() 132 | d2 = ctx.config().testdir() 133 | 134 | ctx.mkdir(d, 0o755) 135 | ctx.rename(d, d2, err=ENOTEMPTY) 136 | ctx.open_dir(d, ro=1) 137 | 138 | # Rename an empty directory over an empty lower dir 139 | def subtest_11(ctx): 140 | """Rename new empty dir over empty lower dir""" 141 | d = ctx.empty_dir() + "-new" + ctx.termslash() 142 | d2 = ctx.empty_dir() + ctx.termslash() 143 | 144 | ctx.mkdir(d, 0o755) 145 | ctx.rename(d, d2) 146 | ctx.open_dir(d2, ro=1) 147 | 148 | # Rename an empty directory over a populated lower dir 149 | def subtest_12(ctx): 150 | """Rename new empty dir over populated lower dir""" 151 | d = ctx.empty_dir() + "-new" + ctx.termslash() 152 | d2 = ctx.non_empty_dir() + ctx.termslash() 153 | 154 | ctx.mkdir(d, 0o755) 155 | ctx.rename(d, d2, err=ENOTEMPTY) 156 | ctx.open_dir(d, ro=1) 157 | ctx.open_dir(d2, ro=1) 158 | ctx.open_file(d2 + "/a", ro=1, err=ENOENT) 159 | 160 | # Rename an empty directory over a removed empty lower dir 161 | def subtest_11(ctx): 162 | """Rename new empty dir over removed empty lower dir""" 163 | d = ctx.empty_dir() + "-new" + ctx.termslash() 164 | d2 = ctx.empty_dir() + ctx.termslash() 165 | 166 | ctx.mkdir(d, 0o755) 167 | ctx.rmdir(d2) 168 | ctx.rename(d, d2) 169 | ctx.open_dir(d2, ro=1) 170 | 171 | # Rename an empty directory over a removed populated lower dir 172 | def subtest_12(ctx): 173 | """Rename new empty dir over removed populated lower dir""" 174 | d = ctx.empty_dir() + "-new" + ctx.termslash() 175 | d2 = ctx.non_empty_dir() + ctx.termslash() 176 | 177 | ctx.mkdir(d, 0o755) 178 | ctx.rmtree(d2) 179 | ctx.rename(d, d2) 180 | ctx.open_file(d2 + "/a", ro=1, err=ENOENT) 181 | ctx.open_dir(d2 + "/pop", ro=1, err=ENOENT) 182 | ctx.open_dir(d2, ro=1) 183 | -------------------------------------------------------------------------------- /tests/rename-new-pop-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename new populated directories 6 | # 7 | ############################################################################### 8 | 9 | # Rename a new populated directory and rename it back again 10 | def subtest_1(ctx): 11 | """Rename new dir and rename back""" 12 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 13 | d2 = ctx.no_dir() + ctx.termslash() 14 | 15 | ctx.mkdir(d, 0o755) 16 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 17 | ctx.rename(d, d2) 18 | ctx.rename(d, d2, err=ENOENT) 19 | ctx.rename(d2, d) 20 | ctx.rename(d2, d, err=ENOENT) 21 | ctx.open_dir(d, ro=1) 22 | ctx.open_dir(d2, ro=1, err=ENOENT) 23 | ctx.open_file(d + "/a", ro=1, read="aaaa") 24 | 25 | # Rename a new directory and remove old name 26 | def subtest_2(ctx): 27 | """Rename new dir and remove old name""" 28 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 29 | d2 = ctx.no_dir() + ctx.termslash() 30 | 31 | ctx.mkdir(d, 0o755) 32 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 33 | ctx.rename(d, d2) 34 | ctx.rmdir(d, err=ENOENT) 35 | ctx.rename(d2, d) 36 | ctx.rename(d2, d, err=ENOENT) 37 | ctx.open_dir(d, ro=1) 38 | ctx.rmdir(d, err=ENOTEMPTY) 39 | ctx.open_dir(d, ro=1) 40 | ctx.open_dir(d2, ro=1, err=ENOENT) 41 | ctx.open_file(d + "/a", ro=1, read="aaaa") 42 | 43 | # Rename a new directory and unlink old name 44 | def subtest_3(ctx): 45 | """Rename new dir and unlink old name""" 46 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 47 | d2 = ctx.no_dir() + ctx.termslash() 48 | 49 | ctx.mkdir(d, 0o755) 50 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 51 | ctx.rename(d, d2) 52 | ctx.unlink(d, err=ENOENT) 53 | ctx.rename(d2, d) 54 | ctx.rename(d2, d, err=ENOENT) 55 | ctx.open_dir(d, ro=1) 56 | ctx.unlink(d, err=EISDIR) 57 | ctx.open_dir(d, ro=1) 58 | ctx.open_dir(d2, ro=1, err=ENOENT) 59 | ctx.open_file(d + "/a", ro=1, read="aaaa") 60 | 61 | # Remove a directory and rename old name 62 | def subtest_4(ctx): 63 | """Remove dir and rename old name""" 64 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 65 | d2 = ctx.no_dir() + ctx.termslash() 66 | 67 | ctx.mkdir(d, 0o755) 68 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 69 | ctx.rmdir(d, err=ENOTEMPTY) 70 | ctx.rename(d, d2) 71 | ctx.rmdir(d, err=ENOENT) 72 | ctx.rmdir(d2, err=ENOTEMPTY) 73 | ctx.open_file(d2 + "/a", ro=1, read="aaaa") 74 | 75 | # Unlink a directory and rename old name 76 | def subtest_5(ctx): 77 | """Unlink new dir and rename old name""" 78 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 79 | d2 = ctx.no_dir() + ctx.termslash() 80 | 81 | ctx.mkdir(d, 0o755) 82 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 83 | ctx.unlink(d, err=EISDIR) 84 | ctx.rename(d, d2) 85 | ctx.unlink(d, err=ENOENT) 86 | ctx.rmdir(d2, err=ENOTEMPTY) 87 | ctx.open_file(d2 + "/a", ro=1, read="aaaa") 88 | 89 | # Rename a new directory twice 90 | def subtest_6(ctx): 91 | """Rename new dir twice""" 92 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 93 | d2 = ctx.no_dir() + ctx.termslash() 94 | d3 = ctx.no_dir() + "x" + ctx.termslash() 95 | 96 | ctx.mkdir(d, 0o755) 97 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 98 | ctx.rename(d, d2) 99 | ctx.rename(d, d2, err=ENOENT) 100 | ctx.rename(d2, d3) 101 | ctx.rename(d2, d3, err=ENOENT) 102 | ctx.open_dir(d, ro=1, err=ENOENT) 103 | ctx.open_dir(d2, ro=1, err=ENOENT) 104 | ctx.open_dir(d3, ro=1) 105 | ctx.open_file(d3 + "/a", ro=1, read="aaaa") 106 | 107 | # Rename a new directory over another 108 | def subtest_7(ctx): 109 | """Rename new dir over another populated dir""" 110 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 111 | d2 = ctx.empty_dir() + ctx.termslash() 112 | 113 | ctx.mkdir(d, 0o755) 114 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 115 | ctx.rename(d, d2) 116 | ctx.open_dir(d, ro=1, err=ENOENT) 117 | ctx.open_dir(d2, ro=1) 118 | ctx.open_file(d2 + "/a", ro=1, read="aaaa") 119 | 120 | # Rename a new directory over itself 121 | def subtest_8(ctx): 122 | """Rename new dir over itself""" 123 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 124 | 125 | ctx.mkdir(d, 0o755) 126 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 127 | ctx.rename(d, d) 128 | ctx.open_dir(d, ro=1) 129 | ctx.open_file(d + "/a", ro=1, read="aaaa") 130 | 131 | # Rename a new directory over a file within that dir 132 | def subtest_9(ctx): 133 | """Rename new dir over a child file""" 134 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 135 | f = ctx.reg_file() + ctx.termslash() 136 | f2 = ctx.non_empty_dir() + "-new/a" + ctx.termslash() 137 | 138 | ctx.mkdir(d, 0o755) 139 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 140 | ctx.rename(d, f, err=ENOTDIR) 141 | ctx.rename(d, f2, err=EINVAL) 142 | ctx.open_dir(d, ro=1) 143 | ctx.open_file(d + "/a", ro=1, read="aaaa") 144 | 145 | # Rename a new directory over a file within another dir 146 | def subtest_10(ctx): 147 | """Rename new dir over a file""" 148 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 149 | f = ctx.non_empty_dir() + "/a" + ctx.termslash() 150 | 151 | ctx.mkdir(d, 0o755) 152 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 153 | ctx.rename(d, f, err=ENOTDIR) 154 | ctx.open_dir(d, ro=1) 155 | ctx.open_file(d + "/a", ro=1, read="aaaa") 156 | 157 | # Rename a new directory over the parent dir 158 | def subtest_11(ctx): 159 | """Rename new dir over parent dir""" 160 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 161 | d2 = ctx.config().testdir() 162 | 163 | ctx.mkdir(d, 0o755) 164 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 165 | ctx.rename(d, d2, err=ENOTEMPTY) 166 | ctx.open_dir(d, ro=1) 167 | ctx.open_file(d + "/a", ro=1, read="aaaa") 168 | 169 | # Rename a new directory over a unioned dir 170 | def subtest_12(ctx): 171 | """Rename new dir over unioned dir""" 172 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 173 | d2 = ctx.non_empty_dir() + ctx.termslash() 174 | 175 | ctx.mkdir(d, 0o755) 176 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 177 | ctx.rename(d, d2, err=ENOTEMPTY) 178 | ctx.open_dir(d, ro=1) 179 | ctx.open_file(d + "/a", ro=1, read="aaaa") 180 | 181 | # Rename a new directory over a removed empty lower dir 182 | def subtest_13(ctx): 183 | """Rename new dir over removed unioned empty dir""" 184 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 185 | d2 = ctx.non_empty_dir() + "/pop/c" + ctx.termslash() 186 | 187 | ctx.mkdir(d, 0o755) 188 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 189 | ctx.rmdir(d2) 190 | ctx.rename(d, d2) 191 | ctx.open_dir(d2, ro=1) 192 | ctx.open_file(d2 + "/a", ro=1, read="aaaa") 193 | 194 | # Rename a new directory over a removed populated lower dir 195 | def subtest_14(ctx): 196 | """Rename new dir over removed unioned dir, different files""" 197 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 198 | d2 = ctx.non_empty_dir() + "/pop" + ctx.termslash() 199 | 200 | ctx.mkdir(d, 0o755) 201 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 202 | ctx.rmtree(d2) 203 | ctx.rename(d, d2) 204 | ctx.open_dir(d2, ro=1) 205 | ctx.open_file(d2 + "/a", ro=1, read="aaaa") 206 | ctx.open_file(d2 + "/b", ro=1, err=ENOENT) 207 | 208 | # Rename a new directory over a removed populated lower dir 209 | def subtest_15(ctx): 210 | """Rename new dir over removed unioned dir, same files""" 211 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 212 | d2 = ctx.non_empty_dir() + "/pop" + ctx.termslash() 213 | 214 | ctx.mkdir(d, 0o755) 215 | ctx.open_file(d + "/b", wo=1, crt=1, write="aaaa") 216 | ctx.rmtree(d2) 217 | ctx.rename(d, d2) 218 | ctx.open_dir(d, ro=1, err=ENOENT) 219 | ctx.open_dir(d2, ro=1) 220 | ctx.open_file(d2 + "/b", ro=1, read="aaaa") 221 | 222 | # Rename a new directory over a removed populated lower dir 223 | def subtest_16(ctx): 224 | """Rename new dir over removed unioned dir, different dirs""" 225 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 226 | d2 = ctx.non_empty_dir() + ctx.termslash() 227 | 228 | ctx.mkdir(d, 0o755) 229 | ctx.mkdir(d + "/pop", 0o755) 230 | ctx.open_file(d + "/pop/x", wo=1, crt=1, write="aaaa") 231 | ctx.rmtree(d2) 232 | ctx.rename(d, d2) 233 | ctx.open_dir(d, ro=1, err=ENOENT) 234 | ctx.open_dir(d2, ro=1) 235 | ctx.open_file(d2 + "/pop/x", ro=1, read="aaaa") 236 | ctx.open_file(d2 + "/pop/b", ro=1, err=ENOENT) 237 | 238 | # Rename a new directory over a removed populated lower dir 239 | def subtest_17(ctx): 240 | """Rename new dir over removed unioned dir, same dirs""" 241 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 242 | d2 = ctx.non_empty_dir() + ctx.termslash() 243 | 244 | ctx.mkdir(d, 0o755) 245 | ctx.mkdir(d + "/pop", 0o755) 246 | ctx.open_file(d + "/pop/b", wo=1, crt=1, write="aaaa") 247 | ctx.rmtree(d2) 248 | ctx.rename(d, d2) 249 | ctx.open_dir(d, ro=1, err=ENOENT) 250 | ctx.open_dir(d2, ro=1) 251 | ctx.open_file(d2 + "/pop/b", ro=1, read="aaaa") 252 | 253 | # Rename a new directory over an unlinked populated lower dir 254 | def subtest_18(ctx): 255 | """Rename new dir over unlinked unioned dir""" 256 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 257 | d2 = ctx.non_empty_dir() + ctx.termslash() 258 | 259 | ctx.mkdir(d, 0o755) 260 | ctx.mkdir(d + "/pop", 0o755) 261 | ctx.open_file(d + "/pop/b", wo=1, crt=1, write="aaaa") 262 | ctx.unlink(d2, err=EISDIR) 263 | ctx.rename(d, d2, err=ENOTEMPTY) 264 | ctx.open_dir(d, ro=1) 265 | ctx.open_dir(d2, ro=1) 266 | ctx.open_file(d + "/pop/b", ro=1, read="aaaa") 267 | ctx.open_file(d2 + "/pop/b", ro=1, read=":aaa:bbb:ccc") 268 | 269 | # Rename a new directory over an emptied populated lower dir 270 | def subtest_19(ctx): 271 | """Rename new dir over an emptied lower dir""" 272 | d = ctx.non_empty_dir() + "-new" + ctx.termslash() 273 | d2 = ctx.non_empty_dir() + "/pop" + ctx.termslash() 274 | 275 | ctx.mkdir(d, 0o755) 276 | ctx.open_file(d + "/a", wo=1, crt=1, write="aaaa") 277 | ctx.rmdir(d2 + "/c") 278 | ctx.unlink(d2 + "/b") 279 | ctx.rename(d, d2) 280 | ctx.open_dir(d2, ro=1) 281 | ctx.open_file(d2 + "/a", ro=1, read="aaaa") 282 | ctx.open_file(d2 + "/b", ro=1, err=ENOENT) 283 | -------------------------------------------------------------------------------- /tests/rename-pop-dir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to rename populated directories 6 | # 7 | ############################################################################### 8 | 9 | # Rename a populated directory and rename it back again 10 | def subtest_1(ctx): 11 | """Rename dir and rename back""" 12 | d = ctx.non_empty_dir() + ctx.termslash() 13 | d2 = ctx.no_dir() + ctx.termslash() 14 | 15 | ctx.rename(d, d2) 16 | ctx.rename(d, d2, err=ENOENT) 17 | ctx.rename(d2, d) 18 | ctx.rename(d2, d, err=ENOENT) 19 | ctx.open_dir(d, ro=1) 20 | ctx.open_dir(d2, ro=1, err=ENOENT) 21 | ctx.open_file(d + "/a", ro=1) 22 | 23 | # Rename a directory and remove old name 24 | def subtest_2(ctx): 25 | """Rename dir and remove old name""" 26 | d = ctx.non_empty_dir() + ctx.termslash() 27 | d2 = ctx.no_dir() + ctx.termslash() 28 | 29 | ctx.rename(d, d2) 30 | ctx.rmdir(d, err=ENOENT) 31 | ctx.rename(d2, d) 32 | ctx.rename(d2, d, err=ENOENT) 33 | ctx.open_dir(d, ro=1) 34 | ctx.rmdir(d, err=ENOTEMPTY) 35 | ctx.open_dir(d, ro=1) 36 | ctx.open_dir(d2, ro=1, err=ENOENT) 37 | ctx.open_file(d + "/a", ro=1) 38 | 39 | # Rename a directory and unlink old name 40 | def subtest_3(ctx): 41 | """Rename dir and unlink old name""" 42 | d = ctx.non_empty_dir() + ctx.termslash() 43 | d2 = ctx.no_dir() + ctx.termslash() 44 | 45 | ctx.rename(d, d2) 46 | ctx.unlink(d, err=ENOENT) 47 | ctx.rename(d2, d) 48 | ctx.rename(d2, d, err=ENOENT) 49 | ctx.open_dir(d, ro=1) 50 | ctx.unlink(d, err=EISDIR) 51 | ctx.open_dir(d, ro=1) 52 | ctx.open_dir(d2, ro=1, err=ENOENT) 53 | ctx.open_file(d + "/a", ro=1) 54 | 55 | # Remove a directory and rename old name 56 | def subtest_4(ctx): 57 | """Remove dir and rename old name""" 58 | d = ctx.non_empty_dir() + ctx.termslash() 59 | d2 = ctx.no_dir() + ctx.termslash() 60 | 61 | ctx.rmdir(d, err=ENOTEMPTY) 62 | ctx.rename(d, d2) 63 | ctx.rmdir(d, err=ENOENT) 64 | ctx.rmdir(d2, err=ENOTEMPTY) 65 | ctx.open_file(d2 + "/a", ro=1) 66 | 67 | # Unlink a directory and rename old name 68 | def subtest_5(ctx): 69 | """Unlink dir and rename old name""" 70 | d = ctx.non_empty_dir() + ctx.termslash() 71 | d2 = ctx.no_dir() + ctx.termslash() 72 | 73 | ctx.unlink(d, err=EISDIR) 74 | ctx.rename(d, d2) 75 | ctx.unlink(d, err=ENOENT) 76 | ctx.rmdir(d2, err=ENOTEMPTY) 77 | ctx.open_file(d2 + "/a", ro=1) 78 | 79 | # Rename a directory twice 80 | def subtest_6(ctx): 81 | """Rename dir twice""" 82 | d = ctx.non_empty_dir() + ctx.termslash() 83 | d2 = ctx.no_dir() + ctx.termslash() 84 | d3 = ctx.no_dir() + "x" + ctx.termslash() 85 | 86 | ctx.rename(d, d2) 87 | ctx.rename(d, d2, err=ENOENT) 88 | ctx.rename(d2, d3) 89 | ctx.rename(d2, d3, err=ENOENT) 90 | ctx.open_dir(d, ro=1, err=ENOENT) 91 | ctx.open_dir(d2, ro=1, err=ENOENT) 92 | ctx.open_dir(d3, ro=1) 93 | ctx.open_file(d3 + "/a", ro=1) 94 | 95 | # Rename a directory over another 96 | def subtest_7(ctx): 97 | """Rename populated dir over another empty dir""" 98 | d = ctx.non_empty_dir() + ctx.termslash() 99 | d2 = ctx.empty_dir() + ctx.termslash() 100 | 101 | ctx.rename(d, d2) 102 | ctx.open_dir(d, ro=1, err=ENOENT) 103 | ctx.open_dir(d2, ro=1) 104 | ctx.open_file(d2 + "/a", ro=1) 105 | 106 | # Rename a directory over itself 107 | def subtest_8(ctx): 108 | """Rename dir over itself""" 109 | d = ctx.non_empty_dir() + ctx.termslash() 110 | 111 | ctx.rename(d, d) 112 | ctx.open_dir(d, ro=1) 113 | ctx.open_file(d + "/a", ro=1) 114 | 115 | # Rename a directory over a file within that dir 116 | def subtest_9(ctx): 117 | """Rename dir over a child file""" 118 | d = ctx.non_empty_dir() + ctx.termslash() 119 | f = ctx.reg_file() + ctx.termslash() 120 | f2 = ctx.non_empty_dir() + "/a" + ctx.termslash() 121 | 122 | ctx.rename(d, f, err=ENOTDIR) 123 | ctx.rename(d, f2, err=EINVAL) 124 | ctx.open_dir(d, ro=1) 125 | ctx.open_file(d + "/a", ro=1) 126 | 127 | # Rename a directory over a file within another dir 128 | def subtest_10(ctx): 129 | """Rename dir over a file""" 130 | d = ctx.non_empty_dir() + "/pop" + ctx.termslash() 131 | f = ctx.non_empty_dir() + "/a" + ctx.termslash() 132 | 133 | ctx.rename(d, f, err=ENOTDIR) 134 | ctx.open_dir(d, ro=1) 135 | ctx.open_file(d + "/b", ro=1) 136 | 137 | # Rename a directory over the parent dir 138 | def subtest_11(ctx): 139 | """Rename dir over parent dir""" 140 | d = ctx.non_empty_dir() + ctx.termslash() 141 | d2 = ctx.config().testdir() 142 | 143 | ctx.rename(d, d2, err=ENOTEMPTY) 144 | ctx.open_dir(d, ro=1) 145 | ctx.open_file(d + "/a", ro=1) 146 | -------------------------------------------------------------------------------- /tests/rmdir.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Try to remove directories 6 | # 7 | ############################################################################### 8 | 9 | # Remove a directory that does not exist in the lower layer 10 | def subtest_1(ctx): 11 | """Remove nonexistent directory""" 12 | d = ctx.no_dir() + ctx.termslash() 13 | 14 | ctx.rmdir(d, err=ENOENT) 15 | ctx.rmdir(d, err=ENOENT) 16 | 17 | # Remove a subdirectory from a dir that does not exist 18 | def subtest_2(ctx): 19 | """Remove subdir from nonexistent directory""" 20 | d = ctx.no_dir() + "/sub" + ctx.termslash() 21 | 22 | ctx.rmdir(d, err=ENOENT) 23 | ctx.rmdir(d, err=ENOENT) 24 | 25 | # Rmdir a file 26 | def subtest_3(ctx): 27 | """Remove-dir a file""" 28 | f = ctx.reg_file() 29 | d = ctx.reg_file() + ctx.termslash() 30 | 31 | ctx.rmdir(d, err=ENOTDIR) 32 | ctx.rmdir(d, err=ENOTDIR) 33 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 34 | 35 | # Remove a subdir from a file 36 | def subtest_4(ctx): 37 | """Remove subdir from file""" 38 | f = ctx.reg_file() 39 | d = ctx.reg_file() + "/sub" + ctx.termslash() 40 | 41 | ctx.rmdir(d, err=ENOTDIR) 42 | ctx.rmdir(d, err=ENOTDIR) 43 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 44 | 45 | # Remove an empty lower directory 46 | def subtest_5(ctx): 47 | """Remove empty dir""" 48 | d = ctx.empty_dir() + ctx.termslash() 49 | subdir = d + "/sub" + ctx.termslash() 50 | 51 | ctx.rmdir(d) 52 | ctx.rmdir(d, err=ENOENT) 53 | ctx.rmdir(subdir, err=ENOENT) 54 | 55 | # Remove a non-existent directory from an empty lower directory 56 | def subtest_6(ctx): 57 | """Remove directory from empty dir""" 58 | d = ctx.empty_dir() + "/sub" + ctx.termslash() 59 | 60 | ctx.rmdir(d, err=ENOENT) 61 | ctx.rmdir(d, err=ENOENT) 62 | 63 | # Remove a populated lower directory 64 | def subtest_7(ctx): 65 | """Remove populated directory""" 66 | d = ctx.non_empty_dir() + ctx.termslash() 67 | f = d + "/a" 68 | 69 | ctx.rmdir(d, err=ENOTEMPTY) 70 | ctx.open_file(f, ro=1, read="") 71 | ctx.unlink(f) 72 | ctx.open_file(f, ro=1, err=ENOENT) 73 | ctx.unlink(f, err=ENOENT) 74 | ctx.rmtree(d) 75 | ctx.open_file(f, ro=1, read="", err=ENOENT) 76 | 77 | # Remove a populated lower directory after creating a file in it 78 | def subtest_8(ctx): 79 | """Remove populated directory with created file""" 80 | d = ctx.empty_dir() + ctx.termslash() 81 | f = d + "/b" 82 | 83 | ctx.open_file(f, wo=1, crt=1, ex=1, write="abcq") 84 | ctx.rmdir(d, err=ENOTEMPTY) 85 | ctx.unlink(f) 86 | ctx.open_file(f, ro=1, err=ENOENT) 87 | ctx.unlink(f, err=ENOENT) 88 | ctx.rmtree(d) 89 | ctx.open_file(f, ro=1, read="", err=ENOENT) 90 | 91 | # Remove a populated lower directory with copied-up file 92 | def subtest_9(ctx): 93 | """Remove populated directory with copied up file""" 94 | d = ctx.non_empty_dir() + ctx.termslash() 95 | f = d + "/a" 96 | 97 | ctx.rmdir(d, err=ENOTEMPTY) 98 | ctx.open_file(f, ro=1, read="") 99 | ctx.open_file(f, wo=1, write="abcd") 100 | ctx.open_file(f, ro=1, read="abcd") 101 | ctx.unlink(f) 102 | ctx.open_file(f, ro=1, err=ENOENT) 103 | ctx.unlink(f, err=ENOENT) 104 | ctx.rmtree(d) 105 | ctx.open_file(f, ro=1, read="", err=ENOENT) 106 | 107 | # Remove a populated lower directory after unlinking a file and creating a dir over it 108 | def subtest_10(ctx): 109 | """Remove populated directory with mkdir after unlink""" 110 | d = ctx.non_empty_dir() + ctx.termslash() 111 | f = d + "/a" 112 | 113 | ctx.rmdir(d, err=ENOTEMPTY) 114 | 115 | ctx.open_file(f, ro=1, read="") 116 | ctx.rmdir(d, err=ENOTEMPTY) 117 | ctx.unlink(f) 118 | ctx.open_file(f, ro=1, err=ENOENT) 119 | ctx.unlink(f, err=ENOENT) 120 | 121 | ctx.mkdir(f, 0o755) 122 | ctx.mkdir(f, 0o755, err=EEXIST) 123 | ctx.rmdir(d, err=ENOTEMPTY) 124 | ctx.rmdir(f) 125 | ctx.rmdir(f, err=ENOENT) 126 | 127 | ctx.rmtree(d) 128 | ctx.open_file(f, ro=1, read="", err=ENOENT) 129 | 130 | # Remove a directory from a populated lower directory and recreate it 131 | def subtest_11(ctx): 132 | """Remove directory from dir""" 133 | d = ctx.non_empty_dir() + ctx.termslash() 134 | pop = d + "/pop" 135 | subdir = pop + "/c" + ctx.termslash() 136 | f = pop + "/b" 137 | 138 | ctx.rmdir(subdir) 139 | ctx.rmdir(subdir, err=ENOENT) 140 | ctx.mkdir(subdir, 0o755) 141 | ctx.mkdir(subdir, 0o755, err=EEXIST) 142 | ctx.open_file(f, ro=1, read=":aaa:bbb:ccc") 143 | 144 | ctx.rmtree(d) 145 | ctx.open_file(f, ro=1, err=ENOENT) 146 | 147 | # Remove directory symlinks pointing to a file 148 | def subtest_12(ctx): 149 | """Remove-dir symlinks to file""" 150 | f = ctx.reg_file() 151 | d = ctx.reg_file() + ctx.termslash() 152 | sym = ctx.direct_sym() + ctx.termslash() 153 | isym = ctx.indirect_sym() + ctx.termslash() 154 | 155 | ctx.rmdir(isym, err=ENOTDIR) 156 | ctx.rmdir(isym, err=ENOTDIR) 157 | ctx.rmdir(sym, err=ENOTDIR) 158 | ctx.rmdir(sym, err=ENOTDIR) 159 | ctx.rmdir(d, err=ENOTDIR) 160 | ctx.rmdir(d, err=ENOTDIR) 161 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 162 | 163 | # Remove a directory over a symlink to a dir 164 | def subtest_13(ctx): 165 | """Remove directory over sym to dir""" 166 | d = ctx.non_empty_dir() + ctx.termslash() 167 | sym = ctx.direct_dir_sym() + ctx.termslash() 168 | 169 | ctx.rmdir(sym, err=ENOTDIR) 170 | ctx.rmdir(sym, err=ENOTDIR) 171 | ctx.rmdir(d, err=ENOTEMPTY) 172 | ctx.open_file(sym + "/a", ro=1, read="") 173 | ctx.open_file(d + "/a", ro=1, read="") 174 | ctx.rmtree(d) 175 | ctx.open_file(sym + "/a", ro=1, err=ENOENT) 176 | ctx.open_file(d + "/a", ro=1, err=ENOENT) 177 | 178 | # Remove a directory over a symlink to a symlink to a dir 179 | def subtest_14(ctx): 180 | """Remove directory over sym to sym to dir""" 181 | d = ctx.non_empty_dir() + ctx.termslash() 182 | sym = ctx.direct_dir_sym() + ctx.termslash() 183 | isym = ctx.indirect_dir_sym() + ctx.termslash() 184 | 185 | ctx.rmdir(isym, err=ENOTDIR) 186 | ctx.rmdir(isym, err=ENOTDIR) 187 | ctx.rmdir(sym, err=ENOTDIR) 188 | ctx.rmdir(d, err=ENOTEMPTY) 189 | ctx.open_file(isym + "/a", ro=1, read="") 190 | ctx.open_file(sym + "/a", ro=1, read="") 191 | ctx.open_file(d + "/a", ro=1, read="") 192 | ctx.rmtree(d) 193 | ctx.open_file(isym + "/a", ro=1, err=ENOENT) 194 | ctx.open_file(sym + "/a", ro=1, err=ENOENT) 195 | ctx.open_file(d + "/a", ro=1, err=ENOENT) 196 | 197 | # Remove a directory over a dangling symlink 198 | def subtest_15(ctx): 199 | """Remove directory over dangling sym""" 200 | d = ctx.no_file() + ctx.termslash() 201 | sym = ctx.pointless() + ctx.termslash() 202 | 203 | ctx.rmdir(sym, err=ENOTDIR) 204 | ctx.rmdir(sym, err=ENOTDIR) 205 | ctx.rmdir(d, err=ENOENT) 206 | 207 | # Remove an empty lower directory, recreate, populate and try to remove 208 | def subtest_16(ctx): 209 | """Remove non-empty opaque directory""" 210 | d = ctx.empty_dir() + ctx.termslash() 211 | f = d + "/b" 212 | 213 | ctx.rmdir(d) 214 | ctx.rmdir(d, err=ENOENT) 215 | ctx.mkdir(d, 0o755) 216 | ctx.open_file(f, wo=1, crt=1, ex=1, write="abcq") 217 | ctx.rmdir(d, err=ENOTEMPTY) 218 | ctx.unlink(f) 219 | ctx.open_file(f, ro=1, err=ENOENT) 220 | ctx.unlink(f, err=ENOENT) 221 | ctx.rmdir(d) 222 | -------------------------------------------------------------------------------- /tests/rmtree-new.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | # Recursive remove populated dir with new subdir 4 | def subtest_1(ctx): 5 | """Recursive remove populated lower dir with new subdir""" 6 | d = ctx.non_empty_dir() + ctx.termslash() 7 | d2 = d + "/b" 8 | 9 | ctx.mkdir(d2, 0o755) 10 | ctx.rmtree(d) 11 | 12 | -------------------------------------------------------------------------------- /tests/rmtree.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | # Recursive remove populated dir with lower files 4 | def subtest_1(ctx): 5 | """Recursive remove populated lower dir with lower files""" 6 | d = ctx.non_empty_dir() + ctx.termslash() 7 | 8 | ctx.rmtree(d) 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/sym1-creat-excl.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open(symlink) of existing file with O_CREAT and O_EXCL 6 | # 7 | ############################################################################### 8 | 9 | # Open(symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(symlink) O_CREAT|O_EXCL|O_RDONLY""" 12 | symlink = ctx.direct_sym() + ctx.termslash() 13 | f = ctx.reg_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, crt=1, ex=1, err=EEXIST) 16 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 17 | 18 | # Open(symlink) write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(symlink) O_CREAT|O_EXCL|O_WRONLY""" 21 | symlink = ctx.direct_sym() + ctx.termslash() 22 | f = ctx.reg_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, crt=1, ex=1, err=EEXIST) 25 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 26 | 27 | # Open(symlink) write-only and append 28 | def subtest_3(ctx): 29 | """Open(symlink) O_CREAT|O_EXCL|O_APPEND|O_WRONLY""" 30 | symlink = ctx.direct_sym() + ctx.termslash() 31 | f = ctx.reg_file() + ctx.termslash() 32 | 33 | ctx.open_file(symlink, app=1, crt=1, ex=1, err=EEXIST) 34 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 35 | 36 | # Open(symlink) read/write and overwrite 37 | def subtest_4(ctx): 38 | """Open(symlink) O_CREAT|O_EXCL|O_RDWR""" 39 | symlink = ctx.direct_sym() + ctx.termslash() 40 | f = ctx.reg_file() + ctx.termslash() 41 | 42 | ctx.open_file(symlink, rw=1, crt=1, ex=1, err=EEXIST) 43 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 44 | 45 | # Open(symlink) read/write and append 46 | def subtest_5(ctx): 47 | """Open(symlink) O_CREAT|O_EXCL|O_APPEND|O_RDWR""" 48 | symlink = ctx.direct_sym() + ctx.termslash() 49 | f = ctx.reg_file() + ctx.termslash() 50 | 51 | ctx.open_file(symlink, ro=1, app=1, crt=1, ex=1, err=EEXIST) 52 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 53 | -------------------------------------------------------------------------------- /tests/sym1-creat.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through symlink of existing file with O_CREAT 6 | # 7 | ############################################################################### 8 | 9 | # Open(symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(symlink) O_CREAT|O_RDONLY""" 12 | symlink = ctx.direct_sym() + ctx.termslash() 13 | f = ctx.reg_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, crt=1, read=":xxx:yyy:zzz") 16 | ctx.open_file(symlink, ro=1, crt=1, read=":xxx:yyy:zzz") 17 | 18 | # Open(symlink) write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(symlink) O_CREAT|O_WRONLY""" 21 | symlink = ctx.direct_sym() + ctx.termslash() 22 | f = ctx.reg_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, crt=1, write="q") 25 | ctx.open_file(symlink, ro=1, crt=1, read="qxxx:yyy:zzz") 26 | ctx.open_file(symlink, wo=1, crt=1, write="p") 27 | ctx.open_file(symlink, ro=1, crt=1, read="pxxx:yyy:zzz") 28 | 29 | # Open(symlink) write-only and append 30 | def subtest_3(ctx): 31 | """Open(symlink) O_CREAT|O_APPEND|O_WRONLY""" 32 | symlink = ctx.direct_sym() + ctx.termslash() 33 | f = ctx.reg_file() + ctx.termslash() 34 | 35 | ctx.open_file(symlink, app=1, crt=1, write="q") 36 | ctx.open_file(symlink, ro=1, crt=1, read=":xxx:yyy:zzzq") 37 | ctx.open_file(symlink, app=1, crt=1, write="p") 38 | ctx.open_file(symlink, ro=1, crt=1, read=":xxx:yyy:zzzqp") 39 | 40 | # Open(symlink) read/write and overwrite 41 | def subtest_4(ctx): 42 | """Open(symlink) O_CREAT|O_RDWR""" 43 | symlink = ctx.direct_sym() + ctx.termslash() 44 | f = ctx.reg_file() + ctx.termslash() 45 | 46 | ctx.open_file(symlink, rw=1, crt=1, write="q") 47 | ctx.open_file(symlink, ro=1, crt=1, read="qxxx:yyy:zzz") 48 | ctx.open_file(symlink, rw=1, crt=1, write="p") 49 | ctx.open_file(symlink, ro=1, crt=1, read="pxxx:yyy:zzz") 50 | 51 | # Open(symlink) read/write and append 52 | def subtest_5(ctx): 53 | """Open(symlink) O_CREAT|O_APPEND|O_RDWR""" 54 | symlink = ctx.direct_sym() + ctx.termslash() 55 | f = ctx.reg_file() + ctx.termslash() 56 | 57 | ctx.open_file(symlink, ro=1, app=1, crt=1, write="q") 58 | ctx.open_file(symlink, ro=1, crt=1, read=":xxx:yyy:zzzq") 59 | ctx.open_file(symlink, ro=1, app=1, crt=1, write="p") 60 | ctx.open_file(symlink, ro=1, crt=1, read=":xxx:yyy:zzzqp") 61 | -------------------------------------------------------------------------------- /tests/sym1-plain.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through symlink of existing file; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open(symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(symlink) O_RDONLY""" 12 | symlink = ctx.direct_sym() + ctx.termslash() 13 | f = ctx.reg_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 16 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 17 | 18 | # Open(symlink) write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(symlink) O_WRONLY""" 21 | symlink = ctx.direct_sym() + ctx.termslash() 22 | f = ctx.reg_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, write="q") 25 | ctx.open_file(symlink, ro=1, read="qxxx:yyy:zzz") 26 | ctx.open_file(symlink, wo=1, write="p") 27 | ctx.open_file(symlink, ro=1, read="pxxx:yyy:zzz") 28 | 29 | # Open(symlink) write-only and append 30 | def subtest_3(ctx): 31 | """Open(symlink) O_APPEND|O_WRONLY""" 32 | symlink = ctx.direct_sym() + ctx.termslash() 33 | f = ctx.reg_file() + ctx.termslash() 34 | 35 | ctx.open_file(symlink, app=1, write="q") 36 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzzq") 37 | ctx.open_file(symlink, app=1, write="p") 38 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzzqp") 39 | 40 | # Open(symlink) read/write and overwrite 41 | def subtest_4(ctx): 42 | """Open(symlink) O_RDWR""" 43 | symlink = ctx.direct_sym() + ctx.termslash() 44 | f = ctx.reg_file() + ctx.termslash() 45 | 46 | ctx.open_file(symlink, rw=1, write="q") 47 | ctx.open_file(symlink, ro=1, read="qxxx:yyy:zzz") 48 | ctx.open_file(symlink, rw=1, write="p") 49 | ctx.open_file(symlink, ro=1, read="pxxx:yyy:zzz") 50 | 51 | # Open(symlink) read/write and append 52 | def subtest_5(ctx): 53 | """Open(symlink) O_APPEND|O_RDWR""" 54 | symlink = ctx.direct_sym() + ctx.termslash() 55 | f = ctx.reg_file() + ctx.termslash() 56 | 57 | ctx.open_file(symlink, ro=1, app=1, write="q") 58 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzzq") 59 | ctx.open_file(symlink, ro=1, app=1, write="p") 60 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzzqp") 61 | -------------------------------------------------------------------------------- /tests/sym1-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through symlink of existing file with O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Truncate and open read-only 10 | def subtest_1(ctx): 11 | """Open(symlink) O_TRUNC|O_RDONLY""" 12 | symlink = ctx.direct_sym() + ctx.termslash() 13 | f = ctx.reg_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, tr=1, read="") 16 | ctx.open_file(symlink, ro=1, tr=1, read="") 17 | 18 | # Truncate, open write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(symlink) O_TRUNC|O_WRONLY""" 21 | symlink = ctx.direct_sym() + ctx.termslash() 22 | f = ctx.reg_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, tr=1, write="q") 25 | ctx.open_file(symlink, ro=1, read="q") 26 | ctx.open_file(symlink, wo=1, tr=1, write="p") 27 | ctx.open_file(symlink, ro=1, read="p") 28 | 29 | # Truncate, open write-only and append 30 | def subtest_3(ctx): 31 | """Open(symlink) O_TRUNC|O_APPEND|O_WRONLY""" 32 | symlink = ctx.direct_sym() + ctx.termslash() 33 | f = ctx.reg_file() + ctx.termslash() 34 | 35 | ctx.open_file(symlink, app=1, tr=1, write="q") 36 | ctx.open_file(symlink, ro=1, read="q") 37 | ctx.open_file(symlink, app=1, tr=1, write="p") 38 | ctx.open_file(symlink, ro=1, read="p") 39 | 40 | # Truncate, open read/write and overwrite 41 | def subtest_4(ctx): 42 | """Open(symlink) O_TRUNC|O_RDWR""" 43 | symlink = ctx.direct_sym() + ctx.termslash() 44 | f = ctx.reg_file() + ctx.termslash() 45 | 46 | ctx.open_file(symlink, rw=1, tr=1, write="q") 47 | ctx.open_file(symlink, ro=1, read="q") 48 | ctx.open_file(symlink, rw=1, tr=1, write="p") 49 | ctx.open_file(symlink, ro=1, read="p") 50 | 51 | # Truncate, open read/write and append 52 | def subtest_5(ctx): 53 | """Open(symlink) O_TRUNC|O_APPEND|O_RDWR""" 54 | symlink = ctx.direct_sym() + ctx.termslash() 55 | f = ctx.reg_file() + ctx.termslash() 56 | 57 | ctx.open_file(symlink, ro=1, app=1, tr=1, write="q") 58 | ctx.open_file(symlink, ro=1, read="q") 59 | ctx.open_file(symlink, ro=1, app=1, tr=1, write="p") 60 | ctx.open_file(symlink, ro=1, read="p") 61 | -------------------------------------------------------------------------------- /tests/sym2-creat-excl.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open(symlink->symlink) of existing file with O_CREAT and O_EXCL 6 | # 7 | ############################################################################### 8 | 9 | # Open(symlink->symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(symlink->symlink) O_CREAT|O_EXCL|O_RDONLY""" 12 | indirect = ctx.indirect_sym() + ctx.termslash() 13 | direct = ctx.direct_sym() + ctx.termslash() 14 | f = ctx.reg_file() + ctx.termslash() 15 | 16 | ctx.open_file(indirect, ro=1, crt=1, ex=1, err=EEXIST) 17 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 18 | 19 | # Open(symlink->symlink) write-only and overwrite 20 | def subtest_2(ctx): 21 | """Open(symlink->symlink) O_CREAT|O_EXCL|O_WRONLY""" 22 | indirect = ctx.indirect_sym() + ctx.termslash() 23 | direct = ctx.direct_sym() + ctx.termslash() 24 | f = ctx.reg_file() + ctx.termslash() 25 | 26 | ctx.open_file(indirect, wo=1, crt=1, ex=1, err=EEXIST) 27 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 28 | 29 | # Open(symlink->symlink) write-only and append 30 | def subtest_3(ctx): 31 | """Open(symlink->symlink) O_CREAT|O_EXCL|O_APPEND|O_WRONLY""" 32 | indirect = ctx.indirect_sym() + ctx.termslash() 33 | direct = ctx.direct_sym() + ctx.termslash() 34 | f = ctx.reg_file() + ctx.termslash() 35 | 36 | ctx.open_file(indirect, app=1, crt=1, ex=1, err=EEXIST) 37 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 38 | 39 | # Open(symlink->symlink) read/write and overwrite 40 | def subtest_4(ctx): 41 | """Open(symlink->symlink) O_CREAT|O_EXCL|O_RDWR""" 42 | indirect = ctx.indirect_sym() + ctx.termslash() 43 | direct = ctx.direct_sym() + ctx.termslash() 44 | f = ctx.reg_file() + ctx.termslash() 45 | 46 | ctx.open_file(indirect, rw=1, crt=1, ex=1, err=EEXIST) 47 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 48 | 49 | # Open(symlink->symlink) read/write and append 50 | def subtest_5(ctx): 51 | """Open(symlink->symlink) O_CREAT|O_EXCL|O_APPEND|O_RDWR""" 52 | indirect = ctx.indirect_sym() + ctx.termslash() 53 | direct = ctx.direct_sym() + ctx.termslash() 54 | f = ctx.reg_file() + ctx.termslash() 55 | 56 | ctx.open_file(indirect, ro=1, app=1, crt=1, ex=1, err=EEXIST) 57 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 58 | -------------------------------------------------------------------------------- /tests/sym2-creat.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through symlink of existing file with O_CREAT 6 | # 7 | ############################################################################### 8 | 9 | # Open(symlink->symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(symlink->symlink) O_CREAT|O_RDONLY""" 12 | indirect = ctx.indirect_sym() + ctx.termslash() 13 | direct = ctx.direct_sym() + ctx.termslash() 14 | f = ctx.reg_file() + ctx.termslash() 15 | 16 | ctx.open_file(indirect, ro=1, crt=1, read=":xxx:yyy:zzz") 17 | ctx.open_file(indirect, ro=1, crt=1, read=":xxx:yyy:zzz") 18 | 19 | # Open(symlink->symlink) write-only and overwrite 20 | def subtest_2(ctx): 21 | """Open(symlink->symlink) O_CREAT|O_WRONLY""" 22 | indirect = ctx.indirect_sym() + ctx.termslash() 23 | direct = ctx.direct_sym() + ctx.termslash() 24 | f = ctx.reg_file() + ctx.termslash() 25 | 26 | ctx.open_file(indirect, wo=1, crt=1, write="q") 27 | ctx.open_file(indirect, ro=1, crt=1, read="qxxx:yyy:zzz") 28 | ctx.open_file(indirect, wo=1, crt=1, write="p") 29 | ctx.open_file(indirect, ro=1, crt=1, read="pxxx:yyy:zzz") 30 | 31 | # Open(symlink->symlink) write-only and append 32 | def subtest_3(ctx): 33 | """Open(symlink->symlink) O_CREAT|O_APPEND|O_WRONLY""" 34 | indirect = ctx.indirect_sym() + ctx.termslash() 35 | direct = ctx.direct_sym() + ctx.termslash() 36 | f = ctx.reg_file() + ctx.termslash() 37 | 38 | ctx.open_file(indirect, app=1, crt=1, write="q") 39 | ctx.open_file(indirect, ro=1, crt=1, read=":xxx:yyy:zzzq") 40 | ctx.open_file(indirect, app=1, crt=1, write="p") 41 | ctx.open_file(indirect, ro=1, crt=1, read=":xxx:yyy:zzzqp") 42 | 43 | # Open(symlink->symlink) read/write and overwrite 44 | def subtest_4(ctx): 45 | """Open(symlink->symlink) O_CREAT|O_RDWR""" 46 | indirect = ctx.indirect_sym() + ctx.termslash() 47 | direct = ctx.direct_sym() + ctx.termslash() 48 | f = ctx.reg_file() + ctx.termslash() 49 | 50 | ctx.open_file(indirect, rw=1, crt=1, write="q") 51 | ctx.open_file(indirect, ro=1, crt=1, read="qxxx:yyy:zzz") 52 | ctx.open_file(indirect, rw=1, crt=1, write="p") 53 | ctx.open_file(indirect, ro=1, crt=1, read="pxxx:yyy:zzz") 54 | 55 | # Open(symlink->symlink) read/write and append 56 | def subtest_5(ctx): 57 | """Open(symlink->symlink) O_CREAT|O_APPEND|O_RDWR""" 58 | indirect = ctx.indirect_sym() + ctx.termslash() 59 | direct = ctx.direct_sym() + ctx.termslash() 60 | f = ctx.reg_file() + ctx.termslash() 61 | 62 | ctx.open_file(indirect, ro=1, app=1, crt=1, write="q") 63 | ctx.open_file(indirect, ro=1, crt=1, read=":xxx:yyy:zzzq") 64 | ctx.open_file(indirect, ro=1, app=1, crt=1, write="p") 65 | ctx.open_file(indirect, ro=1, crt=1, read=":xxx:yyy:zzzqp") 66 | -------------------------------------------------------------------------------- /tests/sym2-plain.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through indirect symlink of existing file; no special flags 6 | # 7 | ############################################################################### 8 | 9 | # Open(symlink->symlink) read-only 10 | def subtest_1(ctx): 11 | """Open(symlink->symlink) O_RDONLY""" 12 | indirect = ctx.indirect_sym() + ctx.termslash() 13 | direct = ctx.direct_sym() + ctx.termslash() 14 | f = ctx.reg_file() + ctx.termslash() 15 | 16 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 17 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 18 | 19 | # Open(symlink->symlink) write-only and overwrite 20 | def subtest_2(ctx): 21 | """Open(symlink->symlink) O_WRONLY""" 22 | indirect = ctx.indirect_sym() + ctx.termslash() 23 | direct = ctx.direct_sym() + ctx.termslash() 24 | f = ctx.reg_file() + ctx.termslash() 25 | 26 | ctx.open_file(indirect, wo=1, write="q") 27 | ctx.open_file(indirect, ro=1, read="qxxx:yyy:zzz") 28 | ctx.open_file(indirect, wo=1, write="p") 29 | ctx.open_file(indirect, ro=1, read="pxxx:yyy:zzz") 30 | 31 | # Open(symlink->symlink) write-only and append 32 | def subtest_3(ctx): 33 | """Open(symlink->symlink) O_APPEND|O_WRONLY""" 34 | indirect = ctx.indirect_sym() + ctx.termslash() 35 | direct = ctx.direct_sym() + ctx.termslash() 36 | f = ctx.reg_file() + ctx.termslash() 37 | 38 | ctx.open_file(indirect, app=1, write="q") 39 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzzq") 40 | ctx.open_file(indirect, app=1, write="p") 41 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzzqp") 42 | 43 | # Open(symlink->symlink) read/write and overwrite 44 | def subtest_4(ctx): 45 | """Open(symlink->symlink) O_RDWR""" 46 | indirect = ctx.indirect_sym() + ctx.termslash() 47 | direct = ctx.direct_sym() + ctx.termslash() 48 | f = ctx.reg_file() + ctx.termslash() 49 | 50 | ctx.open_file(indirect, rw=1, write="q") 51 | ctx.open_file(indirect, ro=1, read="qxxx:yyy:zzz") 52 | ctx.open_file(indirect, rw=1, write="p") 53 | ctx.open_file(indirect, ro=1, read="pxxx:yyy:zzz") 54 | 55 | # Open(symlink->symlink) read/write and append 56 | def subtest_5(ctx): 57 | """Open(symlink->symlink) O_APPEND|O_RDWR""" 58 | indirect = ctx.indirect_sym() + ctx.termslash() 59 | direct = ctx.direct_sym() + ctx.termslash() 60 | f = ctx.reg_file() + ctx.termslash() 61 | 62 | ctx.open_file(indirect, ro=1, app=1, write="q") 63 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzzq") 64 | ctx.open_file(indirect, ro=1, app=1, write="p") 65 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzzqp") 66 | -------------------------------------------------------------------------------- /tests/sym2-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through symlink of existing file with O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Truncate and open read-only 10 | def subtest_1(ctx): 11 | """Open(symlink->symlink) O_TRUNC|O_RDONLY""" 12 | indirect = ctx.indirect_sym() + ctx.termslash() 13 | direct = ctx.direct_sym() + ctx.termslash() 14 | f = ctx.reg_file() + ctx.termslash() 15 | 16 | ctx.open_file(indirect, ro=1, tr=1, read="") 17 | ctx.open_file(indirect, ro=1, tr=1, read="") 18 | 19 | # Truncate, open write-only and overwrite 20 | def subtest_2(ctx): 21 | """Open(symlink->symlink) O_TRUNC|O_WRONLY""" 22 | indirect = ctx.indirect_sym() + ctx.termslash() 23 | direct = ctx.direct_sym() + ctx.termslash() 24 | f = ctx.reg_file() + ctx.termslash() 25 | 26 | ctx.open_file(indirect, wo=1, tr=1, write="q") 27 | ctx.open_file(indirect, ro=1, read="q") 28 | ctx.open_file(indirect, wo=1, tr=1, write="p") 29 | ctx.open_file(indirect, ro=1, read="p") 30 | 31 | # Truncate, open write-only and append 32 | def subtest_3(ctx): 33 | """Open(symlink->symlink) O_TRUNC|O_APPEND|O_WRONLY""" 34 | indirect = ctx.indirect_sym() + ctx.termslash() 35 | direct = ctx.direct_sym() + ctx.termslash() 36 | f = ctx.reg_file() + ctx.termslash() 37 | 38 | ctx.open_file(indirect, app=1, tr=1, write="q") 39 | ctx.open_file(indirect, ro=1, read="q") 40 | ctx.open_file(indirect, app=1, tr=1, write="p") 41 | ctx.open_file(indirect, ro=1, read="p") 42 | 43 | # Truncate, open read/write and overwrite 44 | def subtest_4(ctx): 45 | """Open(symlink->symlink) O_TRUNC|O_RDWR""" 46 | indirect = ctx.indirect_sym() + ctx.termslash() 47 | direct = ctx.direct_sym() + ctx.termslash() 48 | f = ctx.reg_file() + ctx.termslash() 49 | 50 | ctx.open_file(indirect, rw=1, tr=1, write="q") 51 | ctx.open_file(indirect, ro=1, read="q") 52 | ctx.open_file(indirect, rw=1, tr=1, write="p") 53 | ctx.open_file(indirect, ro=1, read="p") 54 | 55 | # Truncate, open read/write and append 56 | def subtest_5(ctx): 57 | """Open(symlink->symlink) O_TRUNC|O_APPEND|O_RDWR""" 58 | indirect = ctx.indirect_sym() + ctx.termslash() 59 | direct = ctx.direct_sym() + ctx.termslash() 60 | f = ctx.reg_file() + ctx.termslash() 61 | 62 | ctx.open_file(indirect, ro=1, app=1, tr=1, write="q") 63 | ctx.open_file(indirect, ro=1, read="q") 64 | ctx.open_file(indirect, ro=1, app=1, tr=1, write="p") 65 | ctx.open_file(indirect, ro=1, read="p") 66 | -------------------------------------------------------------------------------- /tests/symx-creat-excl.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through a broken symlink with O_CREAT|O_EXCL 6 | # 7 | ############################################################################### 8 | 9 | # Create broken link read-only 10 | def subtest_1(ctx): 11 | """Open(broken) O_CREAT|O_EXCL|O_RDONLY""" 12 | symlink = ctx.pointless() + ctx.termslash() 13 | f = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, crt=1, ex=1, err=EEXIST) 16 | 17 | # Open and truncate broken link write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open(broken) O_CREAT|O_EXCL|O_WRONLY""" 20 | symlink = ctx.pointless() + ctx.termslash() 21 | f = ctx.no_file() + ctx.termslash() 22 | 23 | ctx.open_file(symlink, wo=1, crt=1, ex=1, err=EEXIST) 24 | 25 | # Open and truncate broken link write-only and append 26 | def subtest_3(ctx): 27 | """Open(broken) O_CREAT|O_EXCL|O_APPEND|O_WRONLY""" 28 | symlink = ctx.pointless() + ctx.termslash() 29 | f = ctx.no_file() + ctx.termslash() 30 | 31 | ctx.open_file(symlink, app=1, crt=1, ex=1, err=EEXIST) 32 | 33 | # Open and truncate broken link read/write and overwrite 34 | def subtest_4(ctx): 35 | """Open(broken) O_CREAT|O_EXCL|O_RDWR""" 36 | symlink = ctx.pointless() + ctx.termslash() 37 | f = ctx.no_file() + ctx.termslash() 38 | 39 | ctx.open_file(symlink, rw=1, crt=1, ex=1, err=EEXIST) 40 | 41 | # Open and truncate broken link read/write and append 42 | def subtest_5(ctx): 43 | """Open(broken) O_CREAT|O_EXCL|O_APPEND|O_RDWR""" 44 | symlink = ctx.pointless() + ctx.termslash() 45 | f = ctx.no_file() + ctx.termslash() 46 | 47 | ctx.open_file(symlink, ro=1, app=1, crt=1, ex=1, err=EEXIST) 48 | -------------------------------------------------------------------------------- /tests/symx-creat-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through a broken symlink with O_CREAT|O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Open and truncate broken link read-only 10 | def subtest_1(ctx): 11 | """Open(broken) O_CREAT|O_TRUNC|O_RDONLY""" 12 | symlink = ctx.pointless() + ctx.termslash() 13 | f = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, crt=1, tr=1, read="") 16 | ctx.open_file(f, ro=1, read="") 17 | 18 | # Open and truncate broken link write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(broken) O_CREAT|O_TRUNC|O_WRONLY""" 21 | symlink = ctx.pointless() + ctx.termslash() 22 | f = ctx.no_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, crt=1, tr=1, write="q") 25 | ctx.open_file(f, ro=1, read="q") 26 | 27 | # Open and truncate broken link write-only and append 28 | def subtest_3(ctx): 29 | """Open(broken) O_CREAT|O_TRUNC|O_APPEND|O_WRONLY""" 30 | symlink = ctx.pointless() + ctx.termslash() 31 | f = ctx.no_file() + ctx.termslash() 32 | 33 | ctx.open_file(symlink, app=1, crt=1, tr=1, write="q") 34 | ctx.open_file(f, ro=1, read="q") 35 | 36 | # Open and truncate broken link read/write and overwrite 37 | def subtest_4(ctx): 38 | """Open(broken) O_CREAT|O_TRUNC|O_RDWR""" 39 | symlink = ctx.pointless() + ctx.termslash() 40 | f = ctx.no_file() + ctx.termslash() 41 | 42 | ctx.open_file(symlink, rw=1, crt=1, tr=1, write="q") 43 | ctx.open_file(f, ro=1, read="q") 44 | 45 | # Open and truncate broken link read/write and append 46 | def subtest_5(ctx): 47 | """Open(broken) O_CREAT|O_TRUNC|O_APPEND|O_RDWR""" 48 | symlink = ctx.pointless() + ctx.termslash() 49 | f = ctx.no_file() + ctx.termslash() 50 | 51 | ctx.open_file(symlink, ro=1, app=1, crt=1, tr=1, write="q") 52 | ctx.open_file(f, ro=1, read="q") 53 | -------------------------------------------------------------------------------- /tests/symx-creat.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through a broken symlink with O_CREAT 6 | # 7 | ############################################################################### 8 | 9 | # Open/create through broken link read-only 10 | def subtest_1(ctx): 11 | """Open(broken) O_CREAT|O_RDONLY""" 12 | symlink = ctx.pointless() + ctx.termslash() 13 | f = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, crt=1, read="") 16 | ctx.open_file(f, ro=1, read="") 17 | 18 | # Open/create through broken link write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(broken) O_CREAT|O_WRONLY""" 21 | symlink = ctx.pointless() + ctx.termslash() 22 | f = ctx.no_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, crt=1, write="q") 25 | ctx.open_file(f, ro=1, read="q") 26 | 27 | # Open/create through broken link write-only and append 28 | def subtest_3(ctx): 29 | """Open(broken) O_CREAT|O_APPEND|O_WRONLY""" 30 | symlink = ctx.pointless() + ctx.termslash() 31 | f = ctx.no_file() + ctx.termslash() 32 | 33 | ctx.open_file(symlink, app=1, crt=1, write="q") 34 | ctx.open_file(f, ro=1, read="q") 35 | 36 | # Open/create through broken link read/write and overwrite 37 | def subtest_4(ctx): 38 | """Open(broken) O_CREAT|O_RDWR""" 39 | symlink = ctx.pointless() + ctx.termslash() 40 | f = ctx.no_file() + ctx.termslash() 41 | 42 | ctx.open_file(symlink, rw=1, crt=1, write="q") 43 | ctx.open_file(f, ro=1, read="q") 44 | 45 | # Open/create through broken link read/write and append 46 | def subtest_5(ctx): 47 | """Open(broken) O_CREAT|O_APPEND|O_RDWR""" 48 | symlink = ctx.pointless() + ctx.termslash() 49 | f = ctx.no_file() + ctx.termslash() 50 | 51 | ctx.open_file(symlink, ro=1, app=1, crt=1, write="q") 52 | ctx.open_file(f, ro=1, read="q") 53 | -------------------------------------------------------------------------------- /tests/symx-plain.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through a broken symlink 6 | # 7 | ############################################################################### 8 | 9 | # Open broken link read-only 10 | def subtest_1(ctx): 11 | """Open(broken) O_RDONLY""" 12 | symlink = ctx.pointless() + ctx.termslash() 13 | f = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, err=ENOENT) 16 | ctx.open_file(f, ro=1, err=ENOENT) 17 | 18 | # Open broken link write-only and overwrite 19 | def subtest_2(ctx): 20 | """Open(broken) O_WRONLY""" 21 | symlink = ctx.pointless() + ctx.termslash() 22 | f = ctx.no_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, wo=1, err=ENOENT) 25 | ctx.open_file(f, ro=1, err=ENOENT) 26 | 27 | # Open broken link write-only and append 28 | def subtest_3(ctx): 29 | """Open(broken) O_APPEND|O_WRONLY""" 30 | symlink = ctx.pointless() + ctx.termslash() 31 | f = ctx.no_file() + ctx.termslash() 32 | 33 | ctx.open_file(symlink, app=1, err=ENOENT) 34 | ctx.open_file(f, ro=1, err=ENOENT) 35 | 36 | # Open broken link read/write and overwrite 37 | def subtest_4(ctx): 38 | """Open(broken) O_RDWR""" 39 | symlink = ctx.pointless() + ctx.termslash() 40 | f = ctx.no_file() + ctx.termslash() 41 | 42 | ctx.open_file(symlink, rw=1, err=ENOENT) 43 | ctx.open_file(f, ro=1, err=ENOENT) 44 | 45 | # Open broken link read/write and append 46 | def subtest_5(ctx): 47 | """Open(broken) O_APPEND|O_RDWR""" 48 | symlink = ctx.pointless() + ctx.termslash() 49 | f = ctx.no_file() + ctx.termslash() 50 | 51 | ctx.open_file(symlink, ro=1, app=1, err=ENOENT) 52 | ctx.open_file(f, ro=1, err=ENOENT) 53 | -------------------------------------------------------------------------------- /tests/symx-trunc.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Open through a broken symlink with O_TRUNC 6 | # 7 | ############################################################################### 8 | 9 | # Open and truncate broken link read-only 10 | def subtest_1(ctx): 11 | """Open(broken) O_TRUNC|O_RDONLY""" 12 | symlink = ctx.pointless() + ctx.termslash() 13 | f = ctx.no_file() + ctx.termslash() 14 | 15 | ctx.open_file(symlink, ro=1, tr=1, err=ENOENT) 16 | 17 | # Open and truncate broken link write-only and overwrite 18 | def subtest_2(ctx): 19 | """Open(broken) O_TRUNC|O_WRONLY""" 20 | symlink = ctx.pointless() + ctx.termslash() 21 | f = ctx.no_file() + ctx.termslash() 22 | 23 | ctx.open_file(symlink, wo=1, tr=1, err=ENOENT) 24 | 25 | # Open and truncate broken link write-only and append 26 | def subtest_3(ctx): 27 | """Open(broken) O_TRUNC|O_APPEND|O_WRONLY""" 28 | symlink = ctx.pointless() + ctx.termslash() 29 | f = ctx.no_file() + ctx.termslash() 30 | 31 | ctx.open_file(symlink, app=1, tr=1, err=ENOENT) 32 | 33 | # Open and truncate broken link read/write and overwrite 34 | def subtest_4(ctx): 35 | """Open(broken) O_TRUNC|O_RDWR""" 36 | symlink = ctx.pointless() + ctx.termslash() 37 | f = ctx.no_file() + ctx.termslash() 38 | 39 | ctx.open_file(symlink, rw=1, tr=1, err=ENOENT) 40 | 41 | # Open and truncate broken link read/write and append 42 | def subtest_5(ctx): 43 | """Open(broken) O_TRUNC|O_APPEND|O_RDWR""" 44 | symlink = ctx.pointless() + ctx.termslash() 45 | f = ctx.no_file() + ctx.termslash() 46 | 47 | ctx.open_file(symlink, ro=1, app=1, tr=1, err=ENOENT) 48 | -------------------------------------------------------------------------------- /tests/truncate.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Truncate files 6 | # 7 | ############################################################################### 8 | 9 | def subtest_1(ctx): 10 | # Truncate extant file 11 | """Truncate file""" 12 | 13 | key = ":xxx:yyy:zzz" 14 | while len(key) != 29: 15 | key += "\0" 16 | 17 | for loop in range(0, 29): 18 | f = ctx.reg_file() + ctx.termslash() 19 | 20 | if not ctx.termslash(): 21 | pre = ctx.get_file_size(f) 22 | if pre != 12: 23 | raise TestError(f + ": Initial size (" + str(pre) + ") is not 12") 24 | 25 | ctx.truncate(f, loop) 26 | 27 | post = ctx.get_file_size(f) 28 | if post != loop: 29 | raise TestError(f + ": Truncated size (" + str(pre) + ") is not " + str(loop)) 30 | 31 | if post != 0: 32 | ctx.open_file(f, ro=1, read=key[0:loop]) 33 | else: 34 | ctx.truncate(f, loop, err=ENOTDIR) 35 | ctx.incr_filenr() 36 | -------------------------------------------------------------------------------- /tests/unlink.py: -------------------------------------------------------------------------------- 1 | from errno import * 2 | 3 | ############################################################################### 4 | # 5 | # Unlink tests 6 | # 7 | ############################################################################### 8 | 9 | def subtest_1(ctx): 10 | """Unlink file""" 11 | f = ctx.reg_file() + ctx.termslash() 12 | 13 | ctx.unlink(f) 14 | ctx.open_file(f, ro=1, err=ENOENT) 15 | 16 | ctx.unlink(f, err=ENOENT) 17 | ctx.open_file(f, ro=1, err=ENOENT) 18 | 19 | def subtest_2(ctx): 20 | """Unlink direct symlink to file""" 21 | symlink = ctx.direct_sym() + ctx.termslash() 22 | f = ctx.reg_file() + ctx.termslash() 23 | 24 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 25 | ctx.unlink(symlink) 26 | ctx.open_file(symlink, ro=1, err=ENOENT) 27 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 28 | 29 | ctx.unlink(symlink, err=ENOENT) 30 | ctx.open_file(symlink, ro=1, err=ENOENT) 31 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 32 | 33 | def subtest_3(ctx): 34 | """Unlink indirect symlink to file""" 35 | indirect = ctx.indirect_sym() + ctx.termslash() 36 | symlink = ctx.direct_sym() + ctx.termslash() 37 | f = ctx.reg_file() + ctx.termslash() 38 | 39 | ctx.open_file(indirect, ro=1, read=":xxx:yyy:zzz") 40 | ctx.unlink(indirect) 41 | ctx.open_file(indirect, ro=1, err=ENOENT) 42 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 43 | ctx.open_file(f, ro=1, read=":xxx:yyy:zzz") 44 | 45 | ctx.unlink(indirect, err=ENOENT) 46 | ctx.open_file(indirect, ro=1, err=ENOENT) 47 | ctx.open_file(symlink, ro=1, read=":xxx:yyy:zzz") 48 | 49 | # 50 | # 51 | # 52 | def subtest_4(ctx): 53 | """Unlink dir""" 54 | f = ctx.non_empty_dir() + ctx.termslash() 55 | 56 | ctx.unlink(f, err=EISDIR) 57 | ctx.open_dir(f, ro=1) 58 | 59 | ctx.unlink(f, err=EISDIR) 60 | ctx.open_dir(f, ro=1) 61 | 62 | def subtest_5(ctx): 63 | """Unlink direct symlink to dir""" 64 | symlink = ctx.direct_dir_sym() + ctx.termslash() 65 | f = ctx.non_empty_dir() + ctx.termslash() 66 | 67 | ctx.open_dir(symlink, ro=1) 68 | ctx.unlink(symlink) 69 | if not ctx.termslash(): 70 | ctx.open_dir(symlink, ro=1, err=ENOENT) 71 | else: 72 | ctx.open_dir(symlink, ro=1) 73 | ctx.open_dir(f, ro=1) 74 | 75 | ctx.unlink(symlink, err=ENOENT) 76 | if not ctx.termslash(): 77 | ctx.open_dir(symlink, ro=1, err=ENOENT) 78 | else: 79 | ctx.open_dir(symlink, ro=1) 80 | ctx.open_dir(f, ro=1) 81 | 82 | def subtest_6(ctx): 83 | """Unlink indirect symlink to dir""" 84 | indirect = ctx.indirect_dir_sym() + ctx.termslash() 85 | symlink = ctx.direct_dir_sym() + ctx.termslash() 86 | f = ctx.non_empty_dir() + ctx.termslash() 87 | 88 | ctx.open_dir(indirect, ro=1) 89 | ctx.unlink(indirect) 90 | if not ctx.termslash(): 91 | ctx.open_dir(indirect, ro=1, err=ENOENT) 92 | else: 93 | ctx.open_dir(indirect, ro=1) 94 | ctx.open_dir(symlink, ro=1) 95 | ctx.open_dir(f, ro=1) 96 | 97 | ctx.unlink(indirect, err=ENOENT) 98 | if not ctx.termslash(): 99 | ctx.open_dir(indirect, ro=1, err=ENOENT) 100 | else: 101 | ctx.open_dir(indirect, ro=1) 102 | ctx.open_dir(symlink, ro=1) 103 | 104 | # 105 | # 106 | # 107 | def subtest_7(ctx): 108 | """Unlink absent file""" 109 | f = ctx.no_file() + ctx.termslash() 110 | 111 | ctx.unlink(f, err=ENOENT) 112 | ctx.unlink(f, err=ENOENT) 113 | 114 | def subtest_8(ctx): 115 | """Unlink broken symlink to absent file""" 116 | f = ctx.pointless() + ctx.termslash() 117 | 118 | ctx.unlink(f) 119 | ctx.unlink(f, err=ENOENT) 120 | 121 | def subtest_9(ctx): 122 | """Unlink broken symlink""" 123 | f = ctx.pointless() + ctx.termslash() 124 | 125 | ctx.unlink(f) 126 | ctx.unlink(f, err=ENOENT) 127 | 128 | def subtest_10(ctx): 129 | """Unlink absent file pointed to by broken symlink""" 130 | f = ctx.no_file() + ctx.termslash() 131 | 132 | ctx.unlink(f, err=ENOENT) 133 | ctx.unlink(f, err=ENOENT) 134 | -------------------------------------------------------------------------------- /tool_box.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tools for test scripts 3 | # 4 | import os, sys 5 | 6 | class ArgumentError(Exception): 7 | def __init__(self, msg): 8 | self.__msg = msg 9 | def __str__(self): 10 | return self.__msg 11 | 12 | class TestError(Exception): 13 | def __init__(self, msg): 14 | self.__msg = msg 15 | def __str__(self): 16 | return self.__msg 17 | 18 | def exit_error(msg): 19 | print(msg, file=sys.stderr) 20 | sys.exit(1) 21 | 22 | def system(command): 23 | ret = os.system(command) 24 | if ret != 0: 25 | raise RuntimeError("Command failed: " + command) 26 | return True 27 | 28 | def read_file(path): 29 | fd = open(path, "r") 30 | data = fd.read() 31 | del fd 32 | return data 33 | 34 | def write_file(path, data): 35 | fd = open(path, "w") 36 | fd.write(data) 37 | del fd 38 | 39 | def write_kmsg(data): 40 | write_file("/dev/kmsg", data); 41 | 42 | # 43 | # Check for taint (kernel warnings and oopses) 44 | # 45 | current_taint = read_file("/proc/sys/kernel/tainted") 46 | def check_not_tainted(): 47 | taint = read_file("/proc/sys/kernel/tainted") 48 | if taint != current_taint: 49 | raise RuntimeError("TAINTED " + current_taint + " -> ", taint) 50 | 51 | # 52 | # Check if boolean module param is enabled 53 | # 54 | # Return None if module param does not exist 55 | # 56 | def check_bool_modparam(param): 57 | # If overlay is a module, make sure it is loaded before checking its params 58 | try: 59 | system("modprobe overlay 2>/dev/null") 60 | except RuntimeError: 61 | pass 62 | try: 63 | value = read_file("/sys/module/overlay/parameters/" + param) 64 | except FileNotFoundError: 65 | return None 66 | return value.startswith("Y") 67 | 68 | # 69 | # Check if overlay feature is enabled by mount option 70 | # 71 | # Return 'default' if mount option was not provided 72 | # 73 | def check_bool_mntopt(feature, mntopts, default, onopt2=None, offopt2=None): 74 | onopt = feature + "=on" 75 | offopt = feature + "=off" 76 | on = onopt in mntopts or (onopt2 and onopt2 in mntopts) 77 | off = offopt in mntopts or (offopt2 and offopt2 in mntopts) 78 | if on and off: 79 | raise RuntimeError("Conflicting mount options w.r.t feature '" + feature + "': " + mntopts) 80 | if on: 81 | return True 82 | if off: 83 | return False 84 | return default; 85 | -------------------------------------------------------------------------------- /unmount_union.py: -------------------------------------------------------------------------------- 1 | from tool_box import * 2 | 3 | def unmount_union(ctx): 4 | cfg = ctx.config() 5 | system("umount " + cfg.union_mntroot()) 6 | check_not_tainted() 7 | 8 | if cfg.should_mount_lower(): 9 | system("umount " + cfg.lower_mntroot()) 10 | check_not_tainted() 11 | 12 | if cfg.testing_overlayfs(): 13 | # unmount individual layers with maxfs > 0 14 | if cfg.maxfs() > 0 or cfg.is_nested(): 15 | try: 16 | system("umount " + cfg.upper_mntroot() + "/* 2>/dev/null") 17 | except RuntimeError: 18 | pass 19 | check_not_tainted() 20 | 21 | if cfg.should_mount_base(): 22 | system("umount " + cfg.base_mntroot()) 23 | check_not_tainted() 24 | elif cfg.should_mount_upper(): 25 | system("umount " + cfg.upper_mntroot()) 26 | check_not_tainted() 27 | --------------------------------------------------------------------------------