ferret 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +23 -5
- data/TODO +2 -1
- data/ext/analysis.c +838 -177
- data/ext/analysis.h +55 -7
- data/ext/api.c +69 -0
- data/ext/api.h +27 -0
- data/ext/array.c +8 -5
- data/ext/compound_io.c +132 -96
- data/ext/document.c +58 -28
- data/ext/except.c +59 -0
- data/ext/except.h +88 -0
- data/ext/ferret.c +47 -3
- data/ext/ferret.h +3 -0
- data/ext/field.c +15 -9
- data/ext/filter.c +1 -1
- data/ext/fs_store.c +215 -34
- data/ext/global.c +72 -3
- data/ext/global.h +4 -3
- data/ext/hash.c +44 -3
- data/ext/hash.h +9 -0
- data/ext/header.h +58 -0
- data/ext/inc/except.h +88 -0
- data/ext/inc/lang.h +23 -13
- data/ext/ind.c +16 -10
- data/ext/index.h +2 -22
- data/ext/index_io.c +3 -11
- data/ext/index_rw.c +245 -193
- data/ext/lang.h +23 -13
- data/ext/libstemmer.c +92 -0
- data/ext/libstemmer.h +79 -0
- data/ext/modules.h +162 -0
- data/ext/q_boolean.c +34 -21
- data/ext/q_const_score.c +6 -12
- data/ext/q_filtered_query.c +206 -0
- data/ext/q_fuzzy.c +18 -15
- data/ext/q_match_all.c +3 -7
- data/ext/q_multi_phrase.c +10 -14
- data/ext/q_parser.c +29 -2
- data/ext/q_phrase.c +14 -21
- data/ext/q_prefix.c +15 -12
- data/ext/q_range.c +30 -28
- data/ext/q_span.c +13 -21
- data/ext/q_term.c +17 -26
- data/ext/r_analysis.c +693 -21
- data/ext/r_doc.c +11 -12
- data/ext/r_index_io.c +4 -1
- data/ext/r_qparser.c +21 -2
- data/ext/r_search.c +285 -18
- data/ext/ram_store.c +5 -2
- data/ext/search.c +11 -17
- data/ext/search.h +21 -45
- data/ext/similarity.h +67 -0
- data/ext/sort.c +30 -25
- data/ext/stem_ISO_8859_1_danish.c +338 -0
- data/ext/stem_ISO_8859_1_danish.h +16 -0
- data/ext/stem_ISO_8859_1_dutch.c +635 -0
- data/ext/stem_ISO_8859_1_dutch.h +16 -0
- data/ext/stem_ISO_8859_1_english.c +1156 -0
- data/ext/stem_ISO_8859_1_english.h +16 -0
- data/ext/stem_ISO_8859_1_finnish.c +792 -0
- data/ext/stem_ISO_8859_1_finnish.h +16 -0
- data/ext/stem_ISO_8859_1_french.c +1276 -0
- data/ext/stem_ISO_8859_1_french.h +16 -0
- data/ext/stem_ISO_8859_1_german.c +512 -0
- data/ext/stem_ISO_8859_1_german.h +16 -0
- data/ext/stem_ISO_8859_1_italian.c +1091 -0
- data/ext/stem_ISO_8859_1_italian.h +16 -0
- data/ext/stem_ISO_8859_1_norwegian.c +296 -0
- data/ext/stem_ISO_8859_1_norwegian.h +16 -0
- data/ext/stem_ISO_8859_1_porter.c +776 -0
- data/ext/stem_ISO_8859_1_porter.h +16 -0
- data/ext/stem_ISO_8859_1_portuguese.c +1035 -0
- data/ext/stem_ISO_8859_1_portuguese.h +16 -0
- data/ext/stem_ISO_8859_1_spanish.c +1119 -0
- data/ext/stem_ISO_8859_1_spanish.h +16 -0
- data/ext/stem_ISO_8859_1_swedish.c +307 -0
- data/ext/stem_ISO_8859_1_swedish.h +16 -0
- data/ext/stem_KOI8_R_russian.c +701 -0
- data/ext/stem_KOI8_R_russian.h +16 -0
- data/ext/stem_UTF_8_danish.c +344 -0
- data/ext/stem_UTF_8_danish.h +16 -0
- data/ext/stem_UTF_8_dutch.c +653 -0
- data/ext/stem_UTF_8_dutch.h +16 -0
- data/ext/stem_UTF_8_english.c +1176 -0
- data/ext/stem_UTF_8_english.h +16 -0
- data/ext/stem_UTF_8_finnish.c +808 -0
- data/ext/stem_UTF_8_finnish.h +16 -0
- data/ext/stem_UTF_8_french.c +1296 -0
- data/ext/stem_UTF_8_french.h +16 -0
- data/ext/stem_UTF_8_german.c +526 -0
- data/ext/stem_UTF_8_german.h +16 -0
- data/ext/stem_UTF_8_italian.c +1113 -0
- data/ext/stem_UTF_8_italian.h +16 -0
- data/ext/stem_UTF_8_norwegian.c +302 -0
- data/ext/stem_UTF_8_norwegian.h +16 -0
- data/ext/stem_UTF_8_porter.c +794 -0
- data/ext/stem_UTF_8_porter.h +16 -0
- data/ext/stem_UTF_8_portuguese.c +1055 -0
- data/ext/stem_UTF_8_portuguese.h +16 -0
- data/ext/stem_UTF_8_russian.c +709 -0
- data/ext/stem_UTF_8_russian.h +16 -0
- data/ext/stem_UTF_8_spanish.c +1137 -0
- data/ext/stem_UTF_8_spanish.h +16 -0
- data/ext/stem_UTF_8_swedish.c +313 -0
- data/ext/stem_UTF_8_swedish.h +16 -0
- data/ext/stopwords.c +325 -0
- data/ext/store.c +34 -2
- data/ext/tags +2953 -0
- data/ext/term.c +21 -15
- data/ext/termdocs.c +5 -3
- data/ext/utilities.c +446 -0
- data/ext/vector.c +27 -13
- data/lib/ferret/document/document.rb +1 -1
- data/lib/ferret/index/index.rb +44 -6
- data/lib/ferret/query_parser/query_parser.tab.rb +7 -3
- data/lib/rferret.rb +2 -1
- data/test/test_helper.rb +2 -2
- data/test/unit/analysis/ctc_analyzer.rb +401 -0
- data/test/unit/analysis/ctc_tokenstream.rb +423 -0
- data/test/unit/analysis/{tc_letter_tokenizer.rb → rtc_letter_tokenizer.rb} +0 -0
- data/test/unit/analysis/{tc_lower_case_filter.rb → rtc_lower_case_filter.rb} +0 -0
- data/test/unit/analysis/{tc_lower_case_tokenizer.rb → rtc_lower_case_tokenizer.rb} +0 -0
- data/test/unit/analysis/{tc_per_field_analyzer_wrapper.rb → rtc_per_field_analyzer_wrapper.rb} +0 -0
- data/test/unit/analysis/{tc_porter_stem_filter.rb → rtc_porter_stem_filter.rb} +0 -0
- data/test/unit/analysis/{tc_standard_analyzer.rb → rtc_standard_analyzer.rb} +0 -0
- data/test/unit/analysis/{tc_standard_tokenizer.rb → rtc_standard_tokenizer.rb} +0 -0
- data/test/unit/analysis/{tc_stop_analyzer.rb → rtc_stop_analyzer.rb} +0 -0
- data/test/unit/analysis/{tc_stop_filter.rb → rtc_stop_filter.rb} +0 -0
- data/test/unit/analysis/{tc_white_space_analyzer.rb → rtc_white_space_analyzer.rb} +0 -0
- data/test/unit/analysis/{tc_white_space_tokenizer.rb → rtc_white_space_tokenizer.rb} +0 -0
- data/test/unit/analysis/{tc_word_list_loader.rb → rtc_word_list_loader.rb} +0 -0
- data/test/unit/analysis/tc_analyzer.rb +1 -2
- data/test/unit/analysis/{c_token.rb → tc_token.rb} +0 -0
- data/test/unit/document/rtc_field.rb +28 -0
- data/test/unit/document/{c_document.rb → tc_document.rb} +0 -0
- data/test/unit/document/tc_field.rb +82 -12
- data/test/unit/index/{tc_compound_file_io.rb → rtc_compound_file_io.rb} +0 -0
- data/test/unit/index/{tc_field_infos.rb → rtc_field_infos.rb} +0 -0
- data/test/unit/index/{tc_fields_io.rb → rtc_fields_io.rb} +0 -0
- data/test/unit/index/{tc_multiple_term_doc_pos_enum.rb → rtc_multiple_term_doc_pos_enum.rb} +0 -0
- data/test/unit/index/{tc_segment_infos.rb → rtc_segment_infos.rb} +0 -0
- data/test/unit/index/{tc_segment_term_docs.rb → rtc_segment_term_docs.rb} +0 -0
- data/test/unit/index/{tc_segment_term_enum.rb → rtc_segment_term_enum.rb} +0 -0
- data/test/unit/index/{tc_segment_term_vector.rb → rtc_segment_term_vector.rb} +0 -0
- data/test/unit/index/{tc_term_buffer.rb → rtc_term_buffer.rb} +0 -0
- data/test/unit/index/{tc_term_info.rb → rtc_term_info.rb} +0 -0
- data/test/unit/index/{tc_term_infos_io.rb → rtc_term_infos_io.rb} +0 -0
- data/test/unit/index/{tc_term_vectors_io.rb → rtc_term_vectors_io.rb} +0 -0
- data/test/unit/index/{c_index.rb → tc_index.rb} +26 -6
- data/test/unit/index/{c_index_reader.rb → tc_index_reader.rb} +0 -0
- data/test/unit/index/{c_index_writer.rb → tc_index_writer.rb} +0 -0
- data/test/unit/index/{c_term.rb → tc_term.rb} +0 -0
- data/test/unit/index/{c_term_voi.rb → tc_term_voi.rb} +0 -0
- data/test/unit/query_parser/{c_query_parser.rb → rtc_query_parser.rb} +14 -14
- data/test/unit/query_parser/tc_query_parser.rb +24 -16
- data/test/unit/search/{tc_similarity.rb → rtc_similarity.rb} +0 -0
- data/test/unit/search/rtc_sort_field.rb +14 -0
- data/test/unit/search/{c_filter.rb → tc_filter.rb} +11 -11
- data/test/unit/search/{c_fuzzy_query.rb → tc_fuzzy_query.rb} +0 -0
- data/test/unit/search/{c_index_searcher.rb → tc_index_searcher.rb} +0 -0
- data/test/unit/search/{c_search_and_sort.rb → tc_search_and_sort.rb} +0 -0
- data/test/unit/search/{c_sort.rb → tc_sort.rb} +0 -0
- data/test/unit/search/tc_sort_field.rb +20 -7
- data/test/unit/search/{c_spans.rb → tc_spans.rb} +0 -0
- data/test/unit/store/rtc_fs_store.rb +62 -0
- data/test/unit/store/rtc_ram_store.rb +15 -0
- data/test/unit/store/rtm_store.rb +150 -0
- data/test/unit/store/rtm_store_lock.rb +2 -0
- data/test/unit/store/tc_fs_store.rb +54 -40
- data/test/unit/store/tc_ram_store.rb +20 -0
- data/test/unit/store/tm_store.rb +30 -146
- data/test/unit/store/tm_store_lock.rb +66 -0
- data/test/unit/utils/{tc_bit_vector.rb → rtc_bit_vector.rb} +0 -0
- data/test/unit/utils/{tc_date_tools.rb → rtc_date_tools.rb} +0 -0
- data/test/unit/utils/{tc_number_tools.rb → rtc_number_tools.rb} +0 -0
- data/test/unit/utils/{tc_parameter.rb → rtc_parameter.rb} +0 -0
- data/test/unit/utils/{tc_priority_queue.rb → rtc_priority_queue.rb} +0 -0
- data/test/unit/utils/{tc_string_helper.rb → rtc_string_helper.rb} +0 -0
- data/test/unit/utils/{tc_thread.rb → rtc_thread.rb} +0 -0
- data/test/unit/utils/{tc_weak_key_hash.rb → rtc_weak_key_hash.rb} +0 -0
- metadata +360 -289
- data/test/unit/document/c_field.rb +0 -98
- data/test/unit/search/c_sort_field.rb +0 -27
- data/test/unit/store/c_fs_store.rb +0 -76
- data/test/unit/store/c_ram_store.rb +0 -35
- data/test/unit/store/m_store.rb +0 -34
- data/test/unit/store/m_store_lock.rb +0 -68
data/ext/field.c
CHANGED
@@ -47,8 +47,11 @@ FieldInfos *fis_open(Store *store, char *filename)
|
|
47
47
|
{
|
48
48
|
FieldInfos *fis = fis_create();
|
49
49
|
InStream *is = store->open_input(store, filename);
|
50
|
-
|
51
|
-
|
50
|
+
TRY
|
51
|
+
fis_read(fis, is);
|
52
|
+
XFINALLY
|
53
|
+
is_close(is);
|
54
|
+
XENDTRY
|
52
55
|
return fis;
|
53
56
|
}
|
54
57
|
|
@@ -166,13 +169,16 @@ void fis_write(FieldInfos *fis, Store *store, char *segment, char *ext)
|
|
166
169
|
strcpy(fname, segment);
|
167
170
|
strcat(fname, ext);
|
168
171
|
OutStream *os = store->create_output(store, fname);
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
172
|
+
TRY
|
173
|
+
os_write_vint(os, fis->fcnt);
|
174
|
+
for (i = 0; i < fis->fcnt; i++) {
|
175
|
+
fi = fis->by_number[i];
|
176
|
+
os_write_string(os, fi->name);
|
177
|
+
os_write_vint(os, fi_field_info_byte(fi));
|
178
|
+
}
|
179
|
+
XFINALLY
|
180
|
+
os_close(os);
|
181
|
+
XENDTRY
|
176
182
|
}
|
177
183
|
|
178
184
|
FieldInfos *fis_read(FieldInfos *fis, InStream *is)
|
data/ext/filter.c
CHANGED
@@ -56,7 +56,7 @@ char *qfilt_to_s(Filter *self)
|
|
56
56
|
QueryFilter *qf = (QueryFilter *)self->data;
|
57
57
|
Query *query = (Query *)qf->query;
|
58
58
|
char *query_str = query->to_s(query, "");
|
59
|
-
char *filter_str =
|
59
|
+
char *filter_str = strfmt("QueryFilter(%s)", query_str);
|
60
60
|
free(query_str);
|
61
61
|
return filter_str;
|
62
62
|
}
|
data/ext/fs_store.c
CHANGED
@@ -10,55 +10,102 @@
|
|
10
10
|
#include <stdio.h>
|
11
11
|
#include "store.h"
|
12
12
|
|
13
|
+
static char * const FILE_OPEN_ERROR_MSG = "Couldn't open the file to read";
|
14
|
+
static char * const SEEK_ERROR_MSG = "Seek error message";
|
15
|
+
static char * const WRITE_ERROR_MSG = "Write error message";
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Create a filepath for a file in the store using the operating systems
|
19
|
+
* default file seperator.
|
20
|
+
*/
|
13
21
|
static char *join_path(char *buf, const char *base, const char *filename)
|
14
22
|
{
|
15
|
-
|
16
|
-
strcat(buf, "/");
|
17
|
-
strcat(buf, filename);
|
23
|
+
sprintf(buf, "%s/%s", base, filename);
|
18
24
|
return buf;
|
19
25
|
}
|
20
26
|
|
27
|
+
/**
|
28
|
+
* Create the file +filename+ in the +store+.
|
29
|
+
*
|
30
|
+
* @param store the store to create the file in
|
31
|
+
* @param filename the name of the file to create
|
32
|
+
* @throws IO_ERROR if the file cannot be created
|
33
|
+
*/
|
21
34
|
void fs_touch(Store *store, char *filename)
|
22
35
|
{
|
23
36
|
char buf[MAX_PATH];
|
24
37
|
int fd = creat(join_path(buf, store->dir.path, filename), S_IRUSR|S_IWUSR);
|
38
|
+
if (fd == -1)
|
39
|
+
RAISE(IO_ERROR, strerror(errno));
|
25
40
|
close(fd);
|
26
41
|
}
|
27
42
|
|
43
|
+
/**
|
44
|
+
* Return true if a file of name +filename+ exists in +store+.
|
45
|
+
*
|
46
|
+
* @param store the store to check in
|
47
|
+
* @param filename the name of the file to check for
|
48
|
+
* @returns true if the file exists
|
49
|
+
* @throws IO_ERROR if there is an error checking for the files existance
|
50
|
+
*/
|
28
51
|
int fs_exists(Store *store, char *filename)
|
29
52
|
{
|
30
53
|
char buf[MAX_PATH];
|
31
54
|
int fd = open(join_path(buf, store->dir.path, filename), 0);
|
32
55
|
if (fd < 0) {
|
33
|
-
|
56
|
+
if (errno != ENOENT)
|
57
|
+
RAISE(IO_ERROR, strerror(errno));
|
34
58
|
return false;
|
35
59
|
}
|
36
60
|
close(fd);
|
37
61
|
return true;
|
38
62
|
}
|
39
63
|
|
64
|
+
/**
|
65
|
+
* Remove the file +filename+ from the +store+
|
66
|
+
*
|
67
|
+
* @param store the store to remove from
|
68
|
+
* @param filename the name of the file to remove
|
69
|
+
* @returns On success, zero is returned. On error, -1 is returned, and errno
|
70
|
+
* is set appropriately.
|
71
|
+
*/
|
40
72
|
int fs_remove(Store *store, char *filename)
|
41
73
|
{
|
42
74
|
char buf[MAX_PATH];
|
43
75
|
return remove(join_path(buf, store->dir.path, filename));
|
44
76
|
}
|
45
77
|
|
78
|
+
/**
|
79
|
+
* Rename the file in the +store+ from the name +from+ to the name +to+.
|
80
|
+
*
|
81
|
+
* @param store the store to rename the file in
|
82
|
+
* @param from the name of the file to rename
|
83
|
+
* @param to the new name of the file
|
84
|
+
* @returns On success, zero is returned. On error, -1 is returned, and errno
|
85
|
+
* is set appropriately.
|
86
|
+
*/
|
46
87
|
int fs_rename(Store *store, char *from, char *to)
|
47
88
|
{
|
48
89
|
char buf1[MAX_PATH], buf2[MAX_PATH];
|
49
|
-
int ret;
|
50
90
|
|
51
|
-
|
91
|
+
return rename(join_path(buf1, store->dir.path, from),
|
52
92
|
join_path(buf2, store->dir.path, to));
|
53
|
-
|
54
|
-
return ret;
|
55
93
|
}
|
56
94
|
|
95
|
+
/**
|
96
|
+
* Returns the number of files in the store.
|
97
|
+
*
|
98
|
+
* @param store the store to count the files in
|
99
|
+
* @return the number of files in the store
|
100
|
+
* @throws IO_ERROR if there is an error opening the directory
|
101
|
+
*/
|
57
102
|
int fs_count(Store *store)
|
58
103
|
{
|
59
104
|
int cnt = 0;
|
60
|
-
DIR *d = opendir(store->dir.path);
|
61
105
|
struct dirent *de;
|
106
|
+
DIR *d = opendir(store->dir.path);
|
107
|
+
|
108
|
+
if (!d) RAISE(IO_ERROR, strerror(errno));
|
62
109
|
|
63
110
|
while ((de = readdir(d)) != NULL) {
|
64
111
|
if (de->d_name[0] != '.') {
|
@@ -70,12 +117,24 @@ int fs_count(Store *store)
|
|
70
117
|
return cnt;
|
71
118
|
}
|
72
119
|
|
120
|
+
/**
|
121
|
+
* Call the function +func+ with each filename in the store and the arg that
|
122
|
+
* you passed. If you need to open the file you should pass the store as the
|
123
|
+
* argument. If you need to pass more than one argument, you should pass a
|
124
|
+
* struct.
|
125
|
+
*
|
126
|
+
* @param store the store to grab the files from
|
127
|
+
* @param func the function to call with each files name and the +arg+ passed
|
128
|
+
* @param arg the argument to pass to the function
|
129
|
+
* @throws IO_ERROR if there is an error opening the directory
|
130
|
+
*/
|
73
131
|
void fs_each(Store *store, void (*func)(char *fname, void *arg), void *arg)
|
74
132
|
{
|
75
|
-
DIR *d;
|
76
133
|
struct dirent *de;
|
134
|
+
DIR *d = opendir(store->dir.path);
|
135
|
+
|
136
|
+
if (!d) RAISE(IO_ERROR, strerror(errno));
|
77
137
|
|
78
|
-
d = opendir(store->dir.path);
|
79
138
|
while ((de = readdir(d)) != NULL) {
|
80
139
|
if ((strncmp(de->d_name, LOCK_PREFIX, strlen(LOCK_PREFIX)) == 0) ||
|
81
140
|
(de->d_name[0] == '.'))
|
@@ -85,12 +144,19 @@ void fs_each(Store *store, void (*func)(char *fname, void *arg), void *arg)
|
|
85
144
|
closedir(d);
|
86
145
|
}
|
87
146
|
|
147
|
+
/**
|
148
|
+
* Clear all the locks in the store.
|
149
|
+
*
|
150
|
+
* @param store the store to clear the locks from
|
151
|
+
* @throws IO_ERROR if there is an error opening the directory
|
152
|
+
*/
|
88
153
|
void fs_clear_locks(Store *store)
|
89
154
|
{
|
90
|
-
DIR *d;
|
91
155
|
struct dirent *de;
|
156
|
+
DIR *d = opendir(store->dir.path);
|
157
|
+
|
158
|
+
if (!d) RAISE(IO_ERROR, strerror(errno));
|
92
159
|
|
93
|
-
d = opendir(store->dir.path);
|
94
160
|
while ((de = readdir(d)) != NULL) {
|
95
161
|
if (file_is_lock(de->d_name)) {
|
96
162
|
fs_remove(store, de->d_name);
|
@@ -99,6 +165,12 @@ void fs_clear_locks(Store *store)
|
|
99
165
|
closedir(d);
|
100
166
|
}
|
101
167
|
|
168
|
+
/**
|
169
|
+
* Destroy the store.
|
170
|
+
*
|
171
|
+
* @param p the store to destroy
|
172
|
+
* @throws IO_ERROR if there is an error deleting the locks
|
173
|
+
*/
|
102
174
|
void fs_destroy(void *p)
|
103
175
|
{
|
104
176
|
Store *store = (Store *)p;
|
@@ -107,12 +179,19 @@ void fs_destroy(void *p)
|
|
107
179
|
store_destroy(store);
|
108
180
|
}
|
109
181
|
|
182
|
+
/**
|
183
|
+
* Clear all files from the store except the lock files.
|
184
|
+
*
|
185
|
+
* @param store the store to clear all the files from
|
186
|
+
* @throws IO_ERROR if there is an error deleting the files
|
187
|
+
*/
|
110
188
|
void fs_clear(Store *store)
|
111
189
|
{
|
112
|
-
DIR *d;
|
113
190
|
struct dirent *de;
|
191
|
+
DIR *d = opendir(store->dir.path);
|
192
|
+
|
193
|
+
if (!d) RAISE(IO_ERROR, strerror(errno));
|
114
194
|
|
115
|
-
d = opendir(store->dir.path);
|
116
195
|
while ((de = readdir(d)) != NULL) {
|
117
196
|
if (de->d_name[0] != '.' && !file_is_lock(de->d_name)) {
|
118
197
|
fs_remove(store, de->d_name);
|
@@ -121,12 +200,17 @@ void fs_clear(Store *store)
|
|
121
200
|
closedir(d);
|
122
201
|
}
|
123
202
|
|
203
|
+
/**
|
204
|
+
* Clear all files from the store including the lock files.
|
205
|
+
*
|
206
|
+
* @param store the store to clear all the files from
|
207
|
+
* @throws IO_ERROR if there is an error deleting the files
|
208
|
+
*/
|
124
209
|
void fs_clear_all(Store *store)
|
125
210
|
{
|
126
|
-
DIR *d;
|
127
211
|
struct dirent *de;
|
212
|
+
DIR *d = opendir(store->dir.path);
|
128
213
|
|
129
|
-
d = opendir(store->dir.path);
|
130
214
|
while ((de = readdir(d)) != NULL) {
|
131
215
|
if (de->d_name[0] != '.') {
|
132
216
|
fs_remove(store, de->d_name);
|
@@ -135,37 +219,79 @@ void fs_clear_all(Store *store)
|
|
135
219
|
closedir(d);
|
136
220
|
}
|
137
221
|
|
222
|
+
/**
|
223
|
+
* Return the length of the file +filename+ in +store+
|
224
|
+
*
|
225
|
+
* @param store the store to use
|
226
|
+
* @param the name of the file to check the length of
|
227
|
+
* @return the length of the file in bytes
|
228
|
+
* @throws IO_ERROR if there is an error checking the file length
|
229
|
+
*/
|
138
230
|
int fs_length(Store *store, char *filename)
|
139
231
|
{
|
140
232
|
char buf[MAX_PATH];
|
141
233
|
struct stat stt;
|
142
|
-
|
234
|
+
|
235
|
+
if (stat(join_path(buf, store->dir.path, filename), &stt))
|
236
|
+
RAISE(IO_ERROR, strerror(errno));
|
237
|
+
|
143
238
|
return stt.st_size;
|
144
239
|
}
|
145
240
|
|
241
|
+
/**
|
242
|
+
* Flush +len+ characters from +src+ to the output stream +os+
|
243
|
+
*
|
244
|
+
* @param os the output stream to write to
|
245
|
+
* @param src the characters to write to the output stream
|
246
|
+
* @param len the number of characters to write
|
247
|
+
* @throws IO_ERROR if there is an error writing the characters
|
248
|
+
*/
|
146
249
|
void fso_flush_internal(OutStream *os, uchar *src, int len)
|
147
250
|
{
|
148
|
-
fwrite(src, sizeof(uchar), len, (FILE *)os->file)
|
251
|
+
if (len != fwrite(src, sizeof(uchar), len, (FILE *)os->file))
|
252
|
+
RAISE(IO_ERROR, WRITE_ERROR_MSG);
|
149
253
|
}
|
150
254
|
|
255
|
+
/**
|
256
|
+
* Seek +pos+ in the output stream
|
257
|
+
*
|
258
|
+
* @param os the output stream to seek in
|
259
|
+
* @param pos the position to seek in the stream
|
260
|
+
* @throws IO_ERROR if there is an error seeking in the output stream
|
261
|
+
*/
|
151
262
|
void fso_seek_internal(OutStream *os, int pos)
|
152
263
|
{
|
153
|
-
fseek((FILE *)os->file, pos, SEEK_SET)
|
264
|
+
if (fseek((FILE *)os->file, pos, SEEK_SET))
|
265
|
+
RAISE(IO_ERROR, strerror(errno));
|
154
266
|
}
|
155
267
|
|
268
|
+
/**
|
269
|
+
* Close any resources used by the output stream +os+
|
270
|
+
*
|
271
|
+
* @param os the output stream to seek in
|
272
|
+
* @throws IO_ERROR if there is an closing the file
|
273
|
+
*/
|
156
274
|
void fso_close_internal(OutStream *os)
|
157
275
|
{
|
158
|
-
fclose((FILE *)os->file)
|
276
|
+
if (fclose((FILE *)os->file))
|
277
|
+
RAISE(IO_ERROR, strerror(errno));
|
159
278
|
}
|
160
279
|
|
280
|
+
/**
|
281
|
+
* Allocate the resources needed for the output stream in the +store+ with the
|
282
|
+
* name +filename+
|
283
|
+
*
|
284
|
+
* @param store the store to create the output stream in.
|
285
|
+
* @param filename the name of the output stream
|
286
|
+
* @return a newly allocated filestream
|
287
|
+
* @throws IO_ERROR if there is an error opening the output stream resources
|
288
|
+
*/
|
161
289
|
OutStream *fs_create_output(Store *store, const char *filename)
|
162
290
|
{
|
163
291
|
char buf[MAX_PATH];
|
164
292
|
FILE *f = fopen(join_path(buf, store->dir.path, filename), "wb");
|
165
|
-
if (!f)
|
166
|
-
|
167
|
-
buf, strerror(errno));
|
168
|
-
}
|
293
|
+
if (!f) RAISE(IO_ERROR, strerror(errno));
|
294
|
+
|
169
295
|
OutStream *os = os_create();
|
170
296
|
os->file = f;
|
171
297
|
os->flush_internal = &fso_flush_internal;
|
@@ -174,6 +300,17 @@ OutStream *fs_create_output(Store *store, const char *filename)
|
|
174
300
|
return os;
|
175
301
|
}
|
176
302
|
|
303
|
+
/**
|
304
|
+
* Read +len+ characters from the input stream into the +offset+ position in
|
305
|
+
* +b+, an array of unsigned characters.
|
306
|
+
*
|
307
|
+
* @param is the input stream to read from
|
308
|
+
* @param b an array of characters which must be allocated with at least
|
309
|
+
* +offset+ + +len+ bytes
|
310
|
+
* @param offset the position in +b+ to start writing the bytes read
|
311
|
+
* @param len the number of bytes to read
|
312
|
+
* @throws IO_ERROR if there is an error reading from the input stream
|
313
|
+
*/
|
177
314
|
void fsi_read_internal(InStream *is, uchar *b, int offset, int len)
|
178
315
|
{
|
179
316
|
int fd = (int)is->file;
|
@@ -181,39 +318,72 @@ void fsi_read_internal(InStream *is, uchar *b, int offset, int len)
|
|
181
318
|
if (pos != lseek(fd, 0, SEEK_CUR)) {
|
182
319
|
lseek(fd, pos, SEEK_SET);
|
183
320
|
}
|
184
|
-
read(fd, b, len)
|
321
|
+
if (read(fd, b, len) != len) {
|
322
|
+
RAISE(EOF_ERROR, strerror(errno));
|
323
|
+
}
|
185
324
|
}
|
186
325
|
|
326
|
+
/**
|
327
|
+
* Seek position +pos+ in input stream +is+
|
328
|
+
*
|
329
|
+
* @param is the input stream to seek in
|
330
|
+
* @param pos the position to seek
|
331
|
+
* @throws IO_ERROR if the seek fails
|
332
|
+
*/
|
187
333
|
void fsi_seek_internal(InStream *is, int pos)
|
188
334
|
{
|
189
|
-
lseek((int)is->file, pos, SEEK_SET)
|
335
|
+
if (lseek((int)is->file, pos, SEEK_SET) < 0)
|
336
|
+
RAISE(IO_ERROR, strerror(errno));
|
190
337
|
}
|
191
338
|
|
339
|
+
/**
|
340
|
+
* Close the resources allocated to the inputstream +is+
|
341
|
+
*
|
342
|
+
* @param is the input stream to close
|
343
|
+
* @throws IO_ERROR if the close fails
|
344
|
+
*/
|
192
345
|
void fsi_close_internal(InStream *is)
|
193
346
|
{
|
194
347
|
if (!is->is_clone) {
|
195
|
-
close((int)is->file)
|
348
|
+
if (close((int)is->file))
|
349
|
+
RAISE(IO_ERROR, strerror(errno));
|
196
350
|
free(is->d.path);
|
197
351
|
}
|
198
352
|
}
|
199
353
|
|
354
|
+
/**
|
355
|
+
* Clone the input stream. Nothing to do for a file system input stream
|
356
|
+
*/
|
200
357
|
void fsi_clone_internal(InStream *is, InStream *new_is)
|
201
358
|
{ }
|
202
359
|
|
360
|
+
/**
|
361
|
+
* Returns the length of the input stream +is+
|
362
|
+
*
|
363
|
+
* @param is the input stream to get the length of
|
364
|
+
* @throws IO_ERROR if there is an error getting the file length
|
365
|
+
*/
|
203
366
|
int fsi_length(InStream *is)
|
204
367
|
{
|
205
368
|
struct stat stt;
|
206
|
-
fstat((int)is->file, &stt)
|
369
|
+
if (fstat((int)is->file, &stt))
|
370
|
+
RAISE(IO_ERROR, strerror(errno));
|
207
371
|
return stt.st_size;
|
208
372
|
}
|
209
373
|
|
374
|
+
/**
|
375
|
+
* Open an input stream in the +store+ with the name +filename+
|
376
|
+
*
|
377
|
+
* @param store the store to create the input stream in
|
378
|
+
* @param filename the name of the input stream
|
379
|
+
* @throws IO_ERROR if the input stream cannot be opened
|
380
|
+
*/
|
210
381
|
InStream *fs_open_input(Store *store, const char *filename)
|
211
382
|
{
|
212
383
|
char buf[MAX_PATH];
|
213
384
|
int fd = open(join_path(buf, store->dir.path, filename), O_RDONLY);
|
214
|
-
if (fd < 0)
|
215
|
-
|
216
|
-
}
|
385
|
+
if (fd < 0) RAISE(IO_ERROR, FILE_OPEN_ERROR_MSG);
|
386
|
+
|
217
387
|
InStream *is = is_create();
|
218
388
|
is->file = (void *)fd;
|
219
389
|
is->d.path = estrdup(buf);
|
@@ -228,6 +398,11 @@ InStream *fs_open_input(Store *store, const char *filename)
|
|
228
398
|
|
229
399
|
#define LOCK_OBTAIN_TIMEOUT 5
|
230
400
|
|
401
|
+
/**
|
402
|
+
* Obtain a lock on the lock +lock+
|
403
|
+
*
|
404
|
+
* @param lock the lock to obtain
|
405
|
+
*/
|
231
406
|
int fs_lock_obtain(Lock *lock)
|
232
407
|
{
|
233
408
|
int f;
|
@@ -243,12 +418,18 @@ int fs_lock_obtain(Lock *lock)
|
|
243
418
|
}
|
244
419
|
}
|
245
420
|
|
421
|
+
/**
|
422
|
+
* Returns true if +lock+ is locked. To test if the file is locked:wq
|
423
|
+
*
|
424
|
+
* @param lock the lock to test
|
425
|
+
* @throws
|
426
|
+
*/
|
246
427
|
int fs_lock_is_locked(Lock *lock)
|
247
428
|
{
|
248
429
|
int f = open(lock->name, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
|
249
430
|
if (f >= 0) {
|
250
|
-
close(f)
|
251
|
-
|
431
|
+
if (close(f) || remove(lock->name))
|
432
|
+
RAISE(IO_ERROR, strerror(errno));
|
252
433
|
return false;
|
253
434
|
} else {
|
254
435
|
return true;
|