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

Commit7f45980

Browse files
committed
I've improved the contributed vacuumlo command, now it behaves like all other
postgres command line utilites e.g. supports -U, -p, -h, -?, -v, passwordprompt and has a "test mode". In test mode, no large objects are removed,just reported.Mario Weilguni
1 parent5b0fb00 commit7f45980

File tree

1 file changed

+246
-33
lines changed

1 file changed

+246
-33
lines changed

‎contrib/vacuumlo/vacuumlo.c

Lines changed: 246 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.10 2001/09/17 02:30:54 inoue Exp $
11+
* $Header: /cvsroot/pgsql/contrib/vacuumlo/vacuumlo.c,v 1.11 2002/04/24 02:45:51 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
15+
16+
#include<pg_config.h>
1517
#include<stdio.h>
1618
#include<stdlib.h>
1719
#include<string.h>
1820

21+
#ifdefHAVE_TERMIOS_H
22+
#include<termios.h>
23+
#endif
24+
1925
#include<sys/types.h>
2026
#include<sys/stat.h>
2127
#include<fcntl.h>
@@ -28,24 +34,163 @@
2834

2935
#defineBUFSIZE1024
3036

31-
intvacuumlo(char*,int);
37+
externchar*optarg;
38+
externintoptind,opterr,optopt;
39+
40+
struct_param {
41+
char*pg_user;
42+
intpg_prompt;
43+
char*pg_port;
44+
char*pg_host;
45+
intverbose;
46+
intdry_run;
47+
};
48+
49+
intvacuumlo(char*,struct_param*);
50+
char*simple_prompt(constchar*prompt,int ,int);
51+
voidusage(void);
52+
53+
54+
/*
55+
* simple_prompt
56+
*
57+
* Generalized function especially intended for reading in usernames and
58+
* password interactively. Reads from /dev/tty or stdin/stderr.
59+
*
60+
* prompt:The prompt to print
61+
* maxlen:How many characters to accept
62+
* echo:Set to 0 if you want to hide what is entered (for passwords)
63+
*
64+
* Returns a malloc()'ed string with the input (w/o trailing newline).
65+
*/
66+
staticintprompt_state=0;
67+
68+
char*
69+
simple_prompt(constchar*prompt,intmaxlen,intecho)
70+
{
71+
intlength;
72+
char*destination;
73+
FILE*termin,
74+
*termout;
75+
76+
#ifdefHAVE_TERMIOS_H
77+
structtermiost_orig,
78+
t;
79+
#endif
80+
81+
destination= (char*)malloc(maxlen+2);
82+
if (!destination)
83+
returnNULL;
84+
85+
prompt_state=1;/* disable SIGINT */
86+
87+
/*
88+
* Do not try to collapse these into one "w+" mode file. Doesn't work
89+
* on some platforms (eg, HPUX 10.20).
90+
*/
91+
termin=fopen("/dev/tty","r");
92+
termout=fopen("/dev/tty","w");
93+
if (!termin|| !termout)
94+
{
95+
if (termin)
96+
fclose(termin);
97+
if (termout)
98+
fclose(termout);
99+
termin=stdin;
100+
termout=stderr;
101+
}
102+
103+
#ifdefHAVE_TERMIOS_H
104+
if (!echo)
105+
{
106+
tcgetattr(fileno(termin),&t);
107+
t_orig=t;
108+
t.c_lflag &= ~ECHO;
109+
tcsetattr(fileno(termin),TCSAFLUSH,&t);
110+
}
111+
#endif
112+
113+
if (prompt)
114+
{
115+
fputs(prompt,termout);
116+
fflush(termout);
117+
}
118+
119+
if (fgets(destination,maxlen,termin)==NULL)
120+
destination[0]='\0';
121+
122+
length=strlen(destination);
123+
if (length>0&&destination[length-1]!='\n')
124+
{
125+
/* eat rest of the line */
126+
charbuf[128];
127+
intbuflen;
128+
129+
do
130+
{
131+
if (fgets(buf,sizeof(buf),termin)==NULL)
132+
break;
133+
buflen=strlen(buf);
134+
}while (buflen>0&&buf[buflen-1]!='\n');
135+
}
136+
137+
if (length>0&&destination[length-1]=='\n')
138+
/* remove trailing newline */
139+
destination[length-1]='\0';
140+
141+
#ifdefHAVE_TERMIOS_H
142+
if (!echo)
143+
{
144+
tcsetattr(fileno(termin),TCSAFLUSH,&t_orig);
145+
fputs("\n",termout);
146+
fflush(termout);
147+
}
148+
#endif
149+
150+
if (termin!=stdin)
151+
{
152+
fclose(termin);
153+
fclose(termout);
154+
}
155+
156+
prompt_state=0;/* SIGINT okay again */
157+
158+
returndestination;
159+
}
160+
32161

33162

34163
/*
35164
* This vacuums LOs of one database. It returns 0 on success, -1 on failure.
36165
*/
37166
int
38-
vacuumlo(char*database,intverbose)
167+
vacuumlo(char*database,struct_param*param)
39168
{
40169
PGconn*conn;
41170
PGresult*res,
42-
*res2;
171+
*res2;
43172
charbuf[BUFSIZE];
44-
intmatched;
45-
intdeleted;
46-
inti;
173+
intmatched;
174+
intdeleted;
175+
inti;
176+
char*password=NULL;
47177

48-
conn=PQsetdb(NULL,NULL,NULL,NULL,database);
178+
if(param->pg_prompt) {
179+
password=simple_prompt("Password: ",32,0);
180+
if(!password) {
181+
fprintf(stderr,"failed to get password\n");
182+
exit(1);
183+
}
184+
}
185+
186+
conn=PQsetdbLogin(param->pg_host,
187+
param->pg_port,
188+
NULL,
189+
NULL,
190+
database,
191+
param->pg_user,
192+
password
193+
);
49194

50195
/* check to see that the backend connection was successfully made */
51196
if (PQstatus(conn)==CONNECTION_BAD)
@@ -56,8 +201,11 @@ vacuumlo(char *database, int verbose)
56201
return-1;
57202
}
58203

59-
if (verbose)
204+
if (param->verbose) {
60205
fprintf(stdout,"Connected to %s\n",database);
206+
if(param->dry_run)
207+
fprintf(stdout,"Test run: no large objects will be removed!\n");
208+
}
61209

62210
/*
63211
* First we create and populate the LO temp table
@@ -132,7 +280,7 @@ vacuumlo(char *database, int verbose)
132280
table=PQgetvalue(res,i,0);
133281
field=PQgetvalue(res,i,1);
134282

135-
if (verbose)
283+
if (param->verbose)
136284
fprintf(stdout,"Checking %s in %s\n",field,table);
137285

138286
/*
@@ -188,19 +336,22 @@ vacuumlo(char *database, int verbose)
188336
{
189337
Oidlo=atooid(PQgetvalue(res,i,0));
190338

191-
if (verbose)
339+
if (param->verbose)
192340
{
193341
fprintf(stdout,"\rRemoving lo %6u ",lo);
194342
fflush(stdout);
195343
}
196344

197-
if (lo_unlink(conn,lo)<0)
198-
{
199-
fprintf(stderr,"\nFailed to remove lo %u: ",lo);
200-
fprintf(stderr,"%s",PQerrorMessage(conn));
201-
}
202-
else
203-
deleted++;
345+
if(param->dry_run==0) {
346+
if (lo_unlink(conn,lo)<0)
347+
{
348+
fprintf(stderr,"\nFailed to remove lo %u: ",lo);
349+
fprintf(stderr,"%s",PQerrorMessage(conn));
350+
}
351+
else
352+
deleted++;
353+
}else
354+
deleted++;
204355
}
205356
PQclear(res);
206357

@@ -212,33 +363,95 @@ vacuumlo(char *database, int verbose)
212363

213364
PQfinish(conn);
214365

215-
if (verbose)
216-
fprintf(stdout,"\rRemoved %d large objects from %s.\n",
217-
deleted,database);
366+
if (param->verbose)
367+
fprintf(stdout,"\r%s %d large objects from %s.\n",
368+
(param->dry_run?"Would remove":"Removed"),deleted,database);
218369

219370
return0;
220371
}
221372

373+
void
374+
usage(void) {
375+
fprintf(stdout,"vacuumlo removes unreferenced large objects from databases\n\n");
376+
fprintf(stdout,"Usage:\n vacuumlo [options] dbname [dbnames...]\n\n");
377+
fprintf(stdout,"Options:\n");
378+
fprintf(stdout," -v\t\tWrite a lot of output\n");
379+
fprintf(stdout," -n\t\tDon't remove any large object, just show what would be done\n");
380+
fprintf(stdout," -U username\tUsername to connect as\n");
381+
fprintf(stdout," -W\t\tPrompt for password\n");
382+
fprintf(stdout," -h hostname\tDatabase server host\n");
383+
fprintf(stdout," -p port\tDatabase server port\n");
384+
fprintf(stdout," -p port\tDatabase server port\n\n");
385+
}
386+
387+
222388
int
223389
main(intargc,char**argv)
224390
{
225-
intverbose=0;
226-
intarg;
227391
intrc=0;
392+
struct_paramparam;
393+
intc;
394+
intport;
228395

229-
if (argc<2)
230-
{
231-
fprintf(stderr,"Usage: %s [-v] database_name [db2 ... dbn]\n",
232-
argv[0]);
396+
/* Parameter handling */
397+
param.pg_user=NULL;
398+
param.pg_prompt=0;
399+
param.pg_host=NULL;
400+
param.pg_port=0;
401+
param.verbose=0;
402+
param.dry_run=0;
403+
404+
while(1 ) {
405+
c=getopt(argc,argv,"?h:U:p:vnW");
406+
if(c==-1)
407+
break;
408+
409+
switch(c) {
410+
case'?':
411+
if(optopt=='?') {
412+
usage();
413+
exit(0);
414+
}
415+
exit(1);
416+
case':':
417+
exit(1);
418+
case'v':
419+
param.verbose=1;
420+
break;
421+
case'n':
422+
param.dry_run=1;
423+
param.verbose=1;
424+
break;
425+
case'U':
426+
param.pg_user=strdup(optarg);
427+
break;
428+
case'W':
429+
param.pg_prompt=1;
430+
break;
431+
case'p':
432+
port=strtol(optarg,NULL,10);
433+
if( (port<1)|| (port>65535)) {
434+
fprintf(stderr,"[%s]: invalid port number '%s'\n",argv[0],optarg);
233435
exit(1);
436+
}
437+
param.pg_port=strdup(optarg);
438+
break;
439+
case'h':
440+
param.pg_host=strdup(optarg);
441+
break;
442+
}
443+
}
444+
445+
/* No database given? Show usage */
446+
if(optind >=argc-1) {
447+
fprintf(stderr,"vacuumlo: missing required argument: database name\n");
448+
fprintf(stderr,"Try 'vacuumlo -?' for help.\n");
449+
exit(1);
234450
}
235451

236-
for (arg=1;arg<argc;arg++)
237-
{
238-
if (strcmp("-v",argv[arg])==0)
239-
verbose= !verbose;
240-
else
241-
rc+= (vacuumlo(argv[arg],verbose)!=0);
452+
for(c=optind;c<argc;c++) {
453+
/* Work on selected database */
454+
rc+= (vacuumlo(argv[c],&param)!=0);
242455
}
243456

244457
returnrc;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp