summaryrefslogtreecommitdiffstats
path: root/lib/replace/tests/os2_delete.c
blob: a3e45f7bff3c5f0a37488ae008e30053181130e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
  test readdir/unlink pattern that OS/2 uses
  tridge@samba.org July 2005
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include "replace-test.h"

#define NUM_FILES 700
#define READDIR_SIZE 100
#define DELETE_SIZE 4

#define TESTDIR "test.dir"

static int test_readdir_os2_delete_ret;

#define FAILED(d) (printf("failure: readdir [\nFailed for %s - %d = %s\n]\n", d, errno, strerror(errno)), test_readdir_os2_delete_ret = 1)

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif

#ifdef _WIN32
#define mkdir(d,m) _mkdir(d)
#endif

static void cleanup(void)
{
	/* I'm a lazy bastard */
	if (system("rm -rf " TESTDIR)) {
		FAILED("system");
	}
	mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir");
}

static void create_files(void)
{
	int i;
	for (i=0;i<NUM_FILES;i++) {
		char fname[40];
		int fd;
		snprintf(fname, sizeof(fname), TESTDIR "/test%u.txt", i);
		fd = open(fname, O_CREAT|O_RDWR, 0600);
		if (fd < 0) {
			FAILED("open");
		}
		if (close(fd) != 0) {
			FAILED("close");
		}
	}
}

static int os2_delete(DIR *d)
{
	off_t offsets[READDIR_SIZE];
	int i, j;
	struct dirent *de;
	char names[READDIR_SIZE][256];

	/* scan, remembering offsets */
	for (i=0, de=readdir(d);
	     de && i < READDIR_SIZE;
	     de=readdir(d), i++) {
		offsets[i] = telldir(d);
		/* strlcpy not available here */
		snprintf(names[i], sizeof(names[i]), "%s", de->d_name);
	}

	if (i == 0) {
		return 0;
	}

	/* delete the first few */
	for (j=0; j<MIN(i, DELETE_SIZE); j++) {
		char fname[40];
		snprintf(fname, sizeof(fname), TESTDIR "/%s", names[j]);
		unlink(fname) == 0 || FAILED("unlink");
	}

	/* seek to just after the deletion */
	seekdir(d, offsets[j-1]);

	/* return number deleted */
	return j;
}

int test_readdir_os2_delete(void)
{
	int total_deleted = 0;
	DIR *d;
	struct dirent *de;

	test_readdir_os2_delete_ret = 0;

	cleanup();
	create_files();

	d = opendir(TESTDIR "/test0.txt");
	if (d != NULL) FAILED("opendir() on file succeed");
	if (errno != ENOTDIR) FAILED("opendir() on file didn't give ENOTDIR");
	if (d != NULL) closedir(d);

	d = opendir(TESTDIR);

	/* skip past . and .. */
	de = readdir(d);
	strcmp(de->d_name, ".") == 0 || FAILED("match .");
	de = readdir(d);
	strcmp(de->d_name, "..") == 0 || FAILED("match ..");

	while (1) {
		int n = os2_delete(d);
		if (n == 0) break;
		total_deleted += n;
	}
	closedir(d);

	fprintf(stderr, "Deleted %d files of %d\n", total_deleted, NUM_FILES);

	rmdir(TESTDIR) == 0 || FAILED("rmdir");

	if (system("rm -rf " TESTDIR) == -1) {
		FAILED("system");
	}

	return test_readdir_os2_delete_ret;
}