ali@9
|
1 |
#include <stdlib.h>
|
ali@9
|
2 |
#include <stdio.h>
|
ali@9
|
3 |
#include <string.h>
|
ali@9
|
4 |
#include <unistd.h>
|
ali@9
|
5 |
#include <errno.h>
|
ali@9
|
6 |
#include <fcntl.h>
|
ali@9
|
7 |
#ifdef WIN32
|
ali@9
|
8 |
#include <io.h>
|
ali@9
|
9 |
#endif
|
ali@9
|
10 |
#include <glib.h>
|
ali@9
|
11 |
#include <glib/gstdio.h>
|
ali@9
|
12 |
#include <bl/bl.h>
|
ali@9
|
13 |
#include "testcase.h"
|
ali@9
|
14 |
#include "testcaseinput.h"
|
ali@9
|
15 |
|
ali@9
|
16 |
#ifndef O_BINARY
|
ali@9
|
17 |
#define O_BINARY 0
|
ali@9
|
18 |
#endif
|
ali@9
|
19 |
|
ali@9
|
20 |
/*
|
ali@9
|
21 |
* As write(), but with error handling.
|
ali@9
|
22 |
*/
|
ali@9
|
23 |
static size_t write_file(int fd,const char *buf,size_t count,GError **error)
|
ali@9
|
24 |
{
|
ali@9
|
25 |
if (write(fd,buf,count)<count)
|
ali@9
|
26 |
{
|
ali@9
|
27 |
g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
|
ali@9
|
28 |
"Error writing bookloupe input file: %s",g_strerror(errno));
|
ali@9
|
29 |
return -1;
|
ali@9
|
30 |
}
|
ali@9
|
31 |
return count;
|
ali@9
|
32 |
}
|
ali@9
|
33 |
|
ali@9
|
34 |
/*
|
ali@35
|
35 |
* Replace \n with \r\n, U+240A (visible symbol for LF) with \n
|
ali@35
|
36 |
* and U+240D (visible symbol for CR) with \r.
|
ali@9
|
37 |
*/
|
ali@9
|
38 |
static char *unix2dos(const char *text)
|
ali@9
|
39 |
{
|
ali@9
|
40 |
gunichar c;
|
ali@9
|
41 |
const gunichar visible_lf=0x240A;
|
ali@35
|
42 |
const gunichar visible_cr=0x240D;
|
ali@9
|
43 |
GString *string;
|
ali@9
|
44 |
string=g_string_new(NULL);
|
ali@9
|
45 |
while(*text)
|
ali@9
|
46 |
{
|
ali@9
|
47 |
c=g_utf8_get_char(text);
|
ali@9
|
48 |
text=g_utf8_next_char(text);
|
ali@9
|
49 |
if (c=='\n')
|
ali@9
|
50 |
g_string_append(string,"\r\n");
|
ali@9
|
51 |
else if (c==visible_lf)
|
ali@9
|
52 |
g_string_append_c(string,'\n');
|
ali@35
|
53 |
else if (c==visible_cr)
|
ali@35
|
54 |
g_string_append_c(string,'\r');
|
ali@9
|
55 |
else
|
ali@9
|
56 |
g_string_append_unichar(string,c);
|
ali@9
|
57 |
}
|
ali@9
|
58 |
return g_string_free(string,FALSE);
|
ali@9
|
59 |
}
|
ali@9
|
60 |
|
ali@9
|
61 |
/*
|
ali@9
|
62 |
* Create an input file needed for a testcase (as specified in <input>).
|
ali@9
|
63 |
* The file is written in the encoding specified for communicating with
|
ali@9
|
64 |
* bookloupe. The name_used field of <input> is filled in with the name
|
ali@9
|
65 |
* of the created file (which may be different than the name specified
|
ali@9
|
66 |
* if that contained "XXXXXX" to be replaced by a unique string).
|
ali@9
|
67 |
*/
|
ali@9
|
68 |
gboolean testcase_input_create(Testcase *testcase,TestcaseInput *input,
|
ali@9
|
69 |
GError **error)
|
ali@9
|
70 |
{
|
ali@9
|
71 |
int fd;
|
ali@9
|
72 |
size_t n;
|
ali@9
|
73 |
char *filename,*s,*t;
|
ali@9
|
74 |
GError *tmp_err=NULL;
|
ali@9
|
75 |
if (input->contents)
|
ali@9
|
76 |
{
|
ali@9
|
77 |
if (testcase->encoding)
|
ali@9
|
78 |
{
|
ali@9
|
79 |
t=unix2dos(input->contents);
|
ali@9
|
80 |
s=g_convert(t,-1,testcase->encoding,"UTF-8",NULL,&n,&tmp_err);
|
ali@9
|
81 |
g_free(t);
|
ali@9
|
82 |
if (!s)
|
ali@9
|
83 |
{
|
ali@9
|
84 |
g_propagate_prefixed_error(error,tmp_err,
|
ali@9
|
85 |
"Conversion to %s failed: ",testcase->encoding);
|
ali@9
|
86 |
return FALSE;
|
ali@9
|
87 |
}
|
ali@9
|
88 |
}
|
ali@9
|
89 |
else
|
ali@9
|
90 |
{
|
ali@9
|
91 |
s=unix2dos(input->contents);
|
ali@9
|
92 |
n=strlen(s);
|
ali@9
|
93 |
}
|
ali@9
|
94 |
}
|
ali@9
|
95 |
else
|
ali@9
|
96 |
{
|
ali@9
|
97 |
n=0;
|
ali@9
|
98 |
s=NULL;
|
ali@9
|
99 |
}
|
ali@9
|
100 |
g_free(input->name_used);
|
ali@9
|
101 |
input->name_used=NULL;
|
ali@9
|
102 |
if (testcase->tmpdir)
|
ali@9
|
103 |
filename=g_build_filename(testcase->tmpdir,input->name,NULL);
|
ali@9
|
104 |
else
|
ali@9
|
105 |
filename=g_strdup(input->name);
|
ali@9
|
106 |
if (strstr(input->name,"XXXXXX"))
|
ali@9
|
107 |
fd=g_mkstemp(filename);
|
ali@9
|
108 |
else
|
ali@9
|
109 |
fd=g_open(filename,O_WRONLY|O_CREAT|O_EXCL|O_BINARY,0600);
|
ali@9
|
110 |
if (fd<0)
|
ali@9
|
111 |
{
|
ali@9
|
112 |
g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
|
ali@9
|
113 |
"%s: %s",filename,g_strerror(errno));
|
ali@9
|
114 |
g_free(s);
|
ali@9
|
115 |
return FALSE;
|
ali@9
|
116 |
}
|
ali@9
|
117 |
input->name_used=g_strdup(filename+strlen(filename)-strlen(input->name));
|
ali@9
|
118 |
if (n && write_file(fd,s,n,error)!=n)
|
ali@9
|
119 |
{
|
ali@9
|
120 |
g_free(s);
|
ali@9
|
121 |
close(fd);
|
ali@9
|
122 |
(void)g_unlink(filename);
|
ali@9
|
123 |
g_free(filename);
|
ali@9
|
124 |
g_free(input->name_used);
|
ali@9
|
125 |
input->name_used=NULL;
|
ali@9
|
126 |
return FALSE;
|
ali@9
|
127 |
}
|
ali@9
|
128 |
g_free(s);
|
ali@9
|
129 |
if (close(fd)<0)
|
ali@9
|
130 |
{
|
ali@9
|
131 |
g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
|
ali@9
|
132 |
"%s: %s",filename,g_strerror(errno));
|
ali@9
|
133 |
(void)g_unlink(filename);
|
ali@9
|
134 |
g_free(filename);
|
ali@9
|
135 |
g_free(input->name_used);
|
ali@9
|
136 |
input->name_used=NULL;
|
ali@9
|
137 |
return FALSE;
|
ali@9
|
138 |
}
|
ali@9
|
139 |
g_free(filename);
|
ali@9
|
140 |
return TRUE;
|
ali@9
|
141 |
}
|
ali@9
|
142 |
|
ali@9
|
143 |
/*
|
ali@9
|
144 |
* Remove an input file created with testcase_input_create()
|
ali@9
|
145 |
*/
|
ali@9
|
146 |
gboolean testcase_input_remove(Testcase *testcase,TestcaseInput *input,
|
ali@9
|
147 |
GError **error)
|
ali@9
|
148 |
{
|
ali@9
|
149 |
char *filename;
|
ali@9
|
150 |
if (input->name_used)
|
ali@9
|
151 |
{
|
ali@9
|
152 |
if (testcase->tmpdir)
|
ali@9
|
153 |
filename=g_build_filename(testcase->tmpdir,input->name_used,NULL);
|
ali@9
|
154 |
else
|
ali@9
|
155 |
filename=g_strdup(input->name_used);
|
ali@9
|
156 |
if (g_unlink(filename)<0)
|
ali@9
|
157 |
{
|
ali@9
|
158 |
g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
|
ali@9
|
159 |
"%s: %s",filename,g_strerror(errno));
|
ali@9
|
160 |
return FALSE;
|
ali@9
|
161 |
}
|
ali@9
|
162 |
g_free(filename);
|
ali@9
|
163 |
g_free(input->name_used);
|
ali@9
|
164 |
input->name_used=NULL;
|
ali@9
|
165 |
}
|
ali@9
|
166 |
return TRUE;
|
ali@9
|
167 |
}
|
ali@9
|
168 |
|
ali@9
|
169 |
/* Create a new description of an input file needed for a testcase */
|
ali@9
|
170 |
TestcaseInput *testcase_input_new(const char *name,const char *contents)
|
ali@9
|
171 |
{
|
ali@9
|
172 |
TestcaseInput *input;
|
ali@9
|
173 |
input=g_new0(TestcaseInput,1);
|
ali@9
|
174 |
input->name=g_strdup(name);
|
ali@9
|
175 |
input->contents=g_strdup(contents);
|
ali@9
|
176 |
return input;
|
ali@9
|
177 |
}
|
ali@9
|
178 |
|
ali@9
|
179 |
/* Free the description of a testcase input file */
|
ali@9
|
180 |
void testcase_input_free(TestcaseInput *input)
|
ali@9
|
181 |
{
|
ali@9
|
182 |
g_free(input->name);
|
ali@9
|
183 |
g_free(input->name_used);
|
ali@9
|
184 |
g_free(input->contents);
|
ali@9
|
185 |
g_free(input);
|
ali@9
|
186 |
}
|