@@ -80,15 +80,14 @@ convert_and_check_filename(text *arg)
8080
8181
8282/*
83- * Read a section of a file, returning it as text
83+ * Read a section of a file, returning it as bytea
84+ *
85+ * We read the whole of the file when bytes_to_read is nagative.
8486 */
85- Datum
86- pg_read_file ( PG_FUNCTION_ARGS )
87+ static bytea *
88+ read_binary_file ( text * filename_t , int64 seek_offset , int64 bytes_to_read )
8789{
88- text * filename_t = PG_GETARG_TEXT_P (0 );
89- int64 seek_offset = PG_GETARG_INT64 (1 );
90- int64 bytes_to_read = PG_GETARG_INT64 (2 );
91- char * buf ;
90+ bytea * buf ;
9291 size_t nbytes ;
9392 FILE * file ;
9493 char * filename ;
@@ -100,6 +99,29 @@ pg_read_file(PG_FUNCTION_ARGS)
10099
101100 filename = convert_and_check_filename (filename_t );
102101
102+ if (bytes_to_read < 0 )
103+ {
104+ if (seek_offset < 0 )
105+ bytes_to_read = - seek_offset ;
106+ else
107+ {
108+ struct stat fst ;
109+
110+ if (stat (filename , & fst ) < 0 )
111+ ereport (ERROR ,
112+ (errcode_for_file_access (),
113+ errmsg ("could not stat file \"%s\": %m" , filename )));
114+
115+ bytes_to_read = fst .st_size - seek_offset ;
116+ }
117+ }
118+
119+ /* not sure why anyone thought that int64 length was a good idea */
120+ if (bytes_to_read > (MaxAllocSize - VARHDRSZ ))
121+ ereport (ERROR ,
122+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
123+ errmsg ("requested length too large" )));
124+
103125 if ((file = AllocateFile (filename , PG_BINARY_R )) == NULL )
104126 ereport (ERROR ,
105127 (errcode_for_file_access (),
@@ -112,18 +134,7 @@ pg_read_file(PG_FUNCTION_ARGS)
112134 (errcode_for_file_access (),
113135 errmsg ("could not seek in file \"%s\": %m" , filename )));
114136
115- if (bytes_to_read < 0 )
116- ereport (ERROR ,
117- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
118- errmsg ("requested length cannot be negative" )));
119-
120- /* not sure why anyone thought that int64 length was a good idea */
121- if (bytes_to_read > (MaxAllocSize - VARHDRSZ ))
122- ereport (ERROR ,
123- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
124- errmsg ("requested length too large" )));
125-
126- buf = palloc ((Size ) bytes_to_read + VARHDRSZ );
137+ buf = (bytea * ) palloc ((Size ) bytes_to_read + VARHDRSZ );
127138
128139 nbytes = fread (VARDATA (buf ), 1 , (size_t ) bytes_to_read , file );
129140
@@ -132,15 +143,86 @@ pg_read_file(PG_FUNCTION_ARGS)
132143 (errcode_for_file_access (),
133144 errmsg ("could not read file \"%s\": %m" , filename )));
134145
135- /* Make sure the input is valid */
136- pg_verifymbstr (VARDATA (buf ), nbytes , false);
137-
138146 SET_VARSIZE (buf , nbytes + VARHDRSZ );
139147
140148 FreeFile (file );
141149 pfree (filename );
142150
143- PG_RETURN_TEXT_P (buf );
151+ return buf ;
152+ }
153+
154+ /*
155+ * In addition to read_binary_file, verify whether the contents are encoded
156+ * in the database encoding.
157+ */
158+ static text *
159+ read_text_file (text * filename , int64 seek_offset , int64 bytes_to_read )
160+ {
161+ bytea * buf = read_binary_file (filename , seek_offset , bytes_to_read );
162+
163+ /* Make sure the input is valid */
164+ pg_verifymbstr (VARDATA (buf ), VARSIZE (buf ) - VARHDRSZ , false);
165+
166+ /* OK, we can cast it as text safely */
167+ return (text * ) buf ;
168+ }
169+
170+ /*
171+ * Read a section of a file, returning it as text
172+ */
173+ Datum
174+ pg_read_file (PG_FUNCTION_ARGS )
175+ {
176+ text * filename_t = PG_GETARG_TEXT_P (0 );
177+ int64 seek_offset = PG_GETARG_INT64 (1 );
178+ int64 bytes_to_read = PG_GETARG_INT64 (2 );
179+
180+ if (bytes_to_read < 0 )
181+ ereport (ERROR ,
182+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
183+ errmsg ("requested length cannot be negative" )));
184+
185+ PG_RETURN_TEXT_P (read_text_file (filename_t , seek_offset , bytes_to_read ));
186+ }
187+
188+ /*
189+ * Read the whole of a file, returning it as text
190+ */
191+ Datum
192+ pg_read_file_all (PG_FUNCTION_ARGS )
193+ {
194+ text * filename_t = PG_GETARG_TEXT_P (0 );
195+
196+ PG_RETURN_TEXT_P (read_text_file (filename_t , 0 , -1 ));
197+ }
198+
199+ /*
200+ * Read a section of a file, returning it as bytea
201+ */
202+ Datum
203+ pg_read_binary_file (PG_FUNCTION_ARGS )
204+ {
205+ text * filename_t = PG_GETARG_TEXT_P (0 );
206+ int64 seek_offset = PG_GETARG_INT64 (1 );
207+ int64 bytes_to_read = PG_GETARG_INT64 (2 );
208+
209+ if (bytes_to_read < 0 )
210+ ereport (ERROR ,
211+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
212+ errmsg ("requested length cannot be negative" )));
213+
214+ PG_RETURN_BYTEA_P (read_binary_file (filename_t , seek_offset , bytes_to_read ));
215+ }
216+
217+ /*
218+ * Read the whole of a file, returning it as bytea
219+ */
220+ Datum
221+ pg_read_binary_file_all (PG_FUNCTION_ARGS )
222+ {
223+ text * filename_t = PG_GETARG_TEXT_P (0 );
224+
225+ PG_RETURN_BYTEA_P (read_binary_file (filename_t , 0 , -1 ));
144226}
145227
146228/*
0 commit comments