Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3d6ec66

Browse files
committed
Improve pg_upgrade's load_directory() function.
Error out on out-of-memory, rather than returning -1, which the soleexisting caller wasn't checking for anyway. There doesn't seem to beany use-case for making the caller check for failure here.Detect failure return from readdir().Use a less platform-dependent method of calculating the entrysize.It's possible, but not yet confirmed, that this explains bug #6733,in which Mike Wilson reports a pg_upgrade crash that did not occurin 9.1. (Note that load_directory is effectively new code in 9.2,at least on platforms that have scandir().)Fix up comments, avoid uselessly using two counters, reduce the numberof realloc calls to something sane.
1 parent73b796a commit3d6ec66

File tree

3 files changed

+47
-31
lines changed

3 files changed

+47
-31
lines changed

‎contrib/pg_upgrade/file.c

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -224,57 +224,61 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
224224
/*
225225
* load_directory()
226226
*
227-
*Returns count of files that meet theselection criteria coded in
228-
*the function pointed to by selector.Creates anarrayof pointers
229-
*to dirent structures. Address of array returned in namelist.
227+
*Read all the file names in thespecified directory, and return them as
228+
*an array of "struct dirent" pointers.Thearrayaddress is returned in
229+
**namelist, and the function result is the count of file names.
230230
*
231-
* Note that the number of dirent structures needed is dynamically
232-
* allocated using realloc. Realloc can be inefficient if invoked a
233-
* large number of times.
231+
* To free the result data, free each namelist array member, then free the
232+
* namelist array itself.
234233
*/
235234
int
236235
load_directory(constchar*dirname,structdirent***namelist)
237236
{
238237
DIR*dirdesc;
239238
structdirent*direntry;
240239
intcount=0;
241-
intname_num=0;
240+
intallocsize=64;
242241
size_tentrysize;
243242

244-
if ((dirdesc=opendir(dirname))==NULL)
245-
pg_log(PG_FATAL,"could not open directory \"%s\": %s\n",dirname,getErrorText(errno));
243+
*namelist= (structdirent**)
244+
pg_malloc(allocsize*sizeof(structdirent*));
246245

247-
*namelist=NULL;
246+
if ((dirdesc=opendir(dirname))==NULL)
247+
pg_log(PG_FATAL,"could not open directory \"%s\": %s\n",
248+
dirname,getErrorText(errno));
248249

249-
while ((direntry=readdir(dirdesc))!=NULL)
250+
while (errno=0,(direntry=readdir(dirdesc))!=NULL)
250251
{
251-
count++;
252-
253-
*namelist= (structdirent**)realloc((void*) (*namelist),
254-
(size_t) ((name_num+1)*sizeof(structdirent*)));
255-
256-
if (*namelist==NULL)
252+
if (count >=allocsize)
257253
{
258-
closedir(dirdesc);
259-
return-1;
254+
allocsize *=2;
255+
*namelist= (structdirent**)
256+
pg_realloc(*namelist,allocsize*sizeof(structdirent*));
260257
}
261258

262-
entrysize=sizeof(structdirent)-sizeof(direntry->d_name)+
259+
entrysize=offsetof(structdirent,d_name)+
263260
strlen(direntry->d_name)+1;
264261

265-
(*namelist)[name_num]= (structdirent*)malloc(entrysize);
266-
267-
if ((*namelist)[name_num]==NULL)
268-
{
269-
closedir(dirdesc);
270-
return-1;
271-
}
262+
(*namelist)[count]= (structdirent*)pg_malloc(entrysize);
272263

273-
memcpy((*namelist)[name_num],direntry,entrysize);
264+
memcpy((*namelist)[count],direntry,entrysize);
274265

275-
name_num++;
266+
count++;
276267
}
277268

269+
#ifdefWIN32
270+
/*
271+
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
272+
* released version
273+
*/
274+
if (GetLastError()==ERROR_NO_MORE_FILES)
275+
errno=0;
276+
#endif
277+
278+
if (errno)
279+
pg_log(PG_FATAL,"could not read directory \"%s\": %s\n",
280+
dirname,getErrorText(errno));
281+
278282
closedir(dirdesc);
279283

280284
returncount;

‎contrib/pg_upgrade/pg_upgrade.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ prep_status(const char *fmt,...)
429429
__attribute__((format(PG_PRINTF_ATTRIBUTE,1,2)));
430430
voidcheck_ok(void);
431431
char*pg_strdup(constchar*s);
432-
void*pg_malloc(intsize);
432+
void*pg_malloc(size_tsize);
433+
void*pg_realloc(void*ptr,size_tsize);
433434
voidpg_free(void*ptr);
434435
constchar*getErrorText(interrNum);
435436
unsignedintstr2uint(constchar*str);

‎contrib/pg_upgrade/util.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ get_user_info(char **user_name)
183183

184184

185185
void*
186-
pg_malloc(intn)
186+
pg_malloc(size_tn)
187187
{
188188
void*p=malloc(n);
189189

@@ -193,6 +193,17 @@ pg_malloc(int n)
193193
returnp;
194194
}
195195

196+
void*
197+
pg_realloc(void*ptr,size_tn)
198+
{
199+
void*p=realloc(ptr,n);
200+
201+
if (p==NULL)
202+
pg_log(PG_FATAL,"%s: out of memory\n",os_info.progname);
203+
204+
returnp;
205+
}
206+
196207

197208
void
198209
pg_free(void*p)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp