aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-01-03 19:40:33 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2010-01-03 20:03:27 +0200
commitfa78a9f21ff4fd85fb568232c9bee957b9c83497 (patch)
tree597162dff26a81877b5788fc5015fc8b075354b7
parent17f28552af10e72a221a0be16417249852774f1b (diff)
downloadwydawca-fa78a9f21ff4fd85fb568232c9bee957b9c83497.tar.gz
wydawca-fa78a9f21ff4fd85fb568232c9bee957b9c83497.tar.bz2
Improve memory management and optimize function signatures.
* src/wydawca.h (file_triplet): New members: relative_dir, obstk. (virt_tab): Remove spool and reldir from argument lists. (triplet_strdup): New prototype. (move_file, archive_file, symlink_file) (rmsymlink_file, dir_move_file, dir_archive_file) (dir_symlink_file, dir_rmsymlink_file) (null_move_file, null_archive_file) (null_symlink_file, null_rmsymlink_file): Remove spool and reldir from argument lists. * src/directive.c (run_check_script): Use trp->obstk to store the program output. (process_directives): Update calls to vtab interfaces. * src/diskio.c (dir_move_file) (dir_archive_file, dir_symlink_file) (dir_rmsymlink_file): Remove spool and reldir arguments. Use the corresponding members of the struct file_triplet. * src/null.c (null_move_file, null_archive_file) (null_symlink_file, null_rmsymlink_file): Likewise. * src/vtab.c (move_file, archive_file) (symlink_file, rmsymlink_file): Likewise. * src/triplet.c (hash_triplet_free): Free obstack and uploader_list. (triplet_strdup): New function. (register_file): Initialize trp->obstck. (fill_project_name): Fill relative_dir as well. (verify_directive_file): Use triplet_strdup to keep string values.
-rw-r--r--src/directive.c34
-rw-r--r--src/diskio.c61
-rw-r--r--src/null.c22
-rw-r--r--src/triplet.c24
-rw-r--r--src/verify.c38
-rw-r--r--src/vtab.c29
-rw-r--r--src/wydawca.h56
7 files changed, 126 insertions, 138 deletions
diff --git a/src/directive.c b/src/directive.c
index 93830b1..34e5feb 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -406,3 +406,2 @@ run_check_script (const char *script, struct file_triplet *trp,
size_t size, total;
- struct obstack stk;
@@ -494,3 +493,2 @@ run_check_script (const char *script, struct file_triplet *trp,
size = total = 0;
- obstack_init (&stk);
if (debug_level > 2)
@@ -502,6 +500,6 @@ run_check_script (const char *script, struct file_triplet *trp,
logmsg (LOG_DEBUG, _("read: %s"), buf);
- obstack_grow (&stk, buf, len);
+ obstack_grow (&trp->obstk, buf, len);
total += size;
}
- obstack_1grow (&stk, 0);
+ obstack_1grow (&trp->obstk, 0);
if (debug_level > 2)
@@ -515,4 +513,3 @@ run_check_script (const char *script, struct file_triplet *trp,
if (total)
- trp->check_diag = xstrdup (obstack_finish (&stk));
- obstack_free (&stk, NULL);
+ trp->check_diag = obstack_finish (&trp->obstk);
@@ -595,3 +592,2 @@ process_directives (struct file_triplet *trp)
const char *key, *val;
- char *relative_dir;
const struct spool *spool;
@@ -618,10 +614,3 @@ process_directives (struct file_triplet *trp)
case directory_dir:
- /* FIXME: Alloc it in triplet */
- relative_dir = safe_file_name_alloc (val);
- if (!relative_dir || relative_dir[0] == '/')
- {
- logmsg (LOG_ERR, _("%s: invalid directory: %s"),
- trp->file[file_directive].name, val);
- return 1;
- }
+ /* already processed (see fill_project_name in verify.c */
break;
@@ -634,4 +623,4 @@ process_directives (struct file_triplet *trp)
return 1;
- if (move_file (trp, spool, file_dist, relative_dir)
- || move_file (trp, spool, file_signature, relative_dir))
+ if (move_file (trp, file_dist)
+ || move_file (trp, file_signature))
return 1;
@@ -647,3 +636,4 @@ process_directives (struct file_triplet *trp)
case version_dir:
- /* Already processed */
+ /* Already processed. See directive_version_in_range_p,
+ called by verify_directive_format */
break;
@@ -651,3 +641,3 @@ process_directives (struct file_triplet *trp)
case archive_dir:
- if (archive_file (trp, spool, relative_dir, val))
+ if (archive_file (trp, val))
return 1;
@@ -675,4 +665,3 @@ process_directives (struct file_triplet *trp)
else
- rc = symlink_file (trp, spool, relative_dir,
- ws.ws_wordv[0], ws.ws_wordv[1]);
+ rc = symlink_file (trp, ws.ws_wordv[0], ws.ws_wordv[1]);
@@ -685,3 +674,3 @@ process_directives (struct file_triplet *trp)
case rmsymlink_dir:
- if (rmsymlink_file (trp, spool, relative_dir, val))
+ if (rmsymlink_file (trp, val))
return 1;
@@ -696,3 +685,2 @@ process_directives (struct file_triplet *trp)
- free (relative_dir);
UPDATE_STATS (STAT_TRIPLET_SUCCESS);
diff --git a/src/diskio.c b/src/diskio.c
index 1760a88..46526d0 100644
--- a/src/diskio.c
+++ b/src/diskio.c
@@ -110,3 +110,3 @@ create_hierarchy (char *dir, size_t baselen)
/* Create a directory BASE/NAME (with eventual intermediate directories in
- NAME). Use UID and GID as owner ids.
+ NAME).
Do nothing if dry_run_mode is set. */
@@ -374,2 +374,4 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
{
+ int rc = 0;
+
switch (archive->type)
@@ -380,3 +382,6 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
case archive_directory:
- return backup_file (dst_file, dst_dir, file, archive, reldir);
+ if (backup_file (dst_file, dst_dir, file, archive, reldir))
+ return 1;
+ UPDATE_STATS (STAT_ARCHIVES);
+ break;
@@ -385,4 +390,7 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
return 1;
+ UPDATE_STATS (STAT_ARCHIVES);
+ break;
}
- if (!dry_run_mode && unlink (dst_file))
+
+ if (!dry_run_mode && unlink (dst_file) && errno != ENOENT)
{
@@ -396,4 +404,4 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
/* Move the part FILE_ID of the triplet TRP between the directories in
- DPAIR. RELDIR gives relative directory (i.e. the directory part of
- the file name) for backup purposes.
+ TRP->SPOOL. TRP->RELATIVE_DIR gives relative directory (i.e. the
+ directory part of the file name) for backup purposes.
@@ -401,4 +409,3 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
int
-dir_move_file (struct file_triplet *trp, const struct spool *spool,
- enum file_type file_id, const char *reldir)
+dir_move_file (struct file_triplet *trp, enum file_type file_id)
{
@@ -406,3 +413,4 @@ dir_move_file (struct file_triplet *trp, const struct spool *spool,
int rc = 0;
- char *dst_dir = create_directory (spool->dest_dir, reldir);
+ const struct spool *spool = trp->spool;
+ char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir);
@@ -418,3 +426,3 @@ dir_move_file (struct file_triplet *trp, const struct spool *spool,
rc = do_archive_file (dst_file, dst_dir, trp->file[file_id].name,
- &spool->archive, reldir);
+ &spool->archive, trp->relative_dir);
@@ -435,4 +443,3 @@ dir_move_file (struct file_triplet *trp, const struct spool *spool,
int
-archive_single_file (struct file_triplet *trp, const struct spool *spool,
- const char *file_name, const char *reldir,
+archive_single_file (struct file_triplet *trp, const char *file_name,
int noentok)
@@ -441,3 +448,4 @@ archive_single_file (struct file_triplet *trp, const struct spool *spool,
int rc = 0;
- char *dst_dir = create_directory (spool->dest_dir, reldir);
+ const struct spool *spool = trp->spool;
+ char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir);
@@ -461,5 +469,3 @@ archive_single_file (struct file_triplet *trp, const struct spool *spool,
rc = do_archive_file (dst_file, dst_dir, file_name, &spool->archive,
- reldir);
- if (rc == 0)
- UPDATE_STATS (STAT_ARCHIVES);
+ trp->relative_dir);
}
@@ -504,4 +510,3 @@ make_signame (const char *file_name)
int
-dir_archive_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name)
+dir_archive_file (struct file_triplet *trp, const char *file_name)
{
@@ -510,6 +515,6 @@ dir_archive_file (struct file_triplet *trp, const struct spool *spool,
- rc = archive_single_file (trp, spool, file_name, reldir, 0);
+ rc = archive_single_file (trp, file_name, 0);
if (rc == 0 && archive_signatures && (signame = make_signame (file_name)))
{
- rc = archive_single_file (trp, spool, signame, reldir, 1);
+ rc = archive_single_file (trp, signame, 1);
free (signame);
@@ -520,3 +525,3 @@ dir_archive_file (struct file_triplet *trp, const struct spool *spool,
/* Create a symbolic link from WANTED_SRC to WANTED_DST in the subdirectory
- RELDIR of DPAIR->dest_dir. Get ownership information from TRP.
+ TRP->relative_dir of SPOOL->dest_dir.
@@ -524,4 +529,3 @@ dir_archive_file (struct file_triplet *trp, const struct spool *spool,
int
-dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir,
+dir_symlink_file (struct file_triplet *trp,
const char *wanted_src, const char *wanted_dst)
@@ -530,3 +534,4 @@ dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
struct saved_cwd cwd;
- char *dst_dir = create_directory (spool->dest_dir, reldir);
+ const struct spool *spool = trp->spool;
+ char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir);
char *src, *dst;
@@ -676,5 +681,3 @@ do_rmsymlink_file (const char *dst_file, int noentok)
-/* Remove the symbolic link DPAIR->dest_dir/RELDIR/FILE_NAME
-
- Get ownership information from TRP.
+/* Remove the symbolic link TRP->spool->dest_dir/TRP->relative_dir/FILE_NAME
@@ -682,4 +685,3 @@ do_rmsymlink_file (const char *dst_file, int noentok)
int
-dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name)
+dir_rmsymlink_file (struct file_triplet *trp, const char *file_name)
{
@@ -688,3 +690,4 @@ dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
char *signame;
- char *dst_dir = create_directory (spool->dest_dir, reldir);
+ const struct spool *spool = trp->spool;
+ char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir);
diff --git a/src/null.c b/src/null.c
index 4a443e3..c37ade3 100644
--- a/src/null.c
+++ b/src/null.c
@@ -19,5 +19,5 @@
int
-null_move_file (struct file_triplet *trp, const struct spool *spool,
- enum file_type file_id, const char *reldir)
+null_move_file (struct file_triplet *trp, enum file_type file_id)
{
+ const struct spool *spool = trp->spool;
const char *file_name = trp->file[file_id].name;
@@ -25,3 +25,3 @@ null_move_file (struct file_triplet *trp, const struct spool *spool,
logmsg (LOG_DEBUG, _("spool %s: installing file `%s/%s'"),
- spool->tag, reldir, file_name);
+ spool->tag, trp->relative_dir, file_name);
UPDATE_STATS (STAT_UPLOADS);
@@ -37,7 +37,7 @@ null_move_file (struct file_triplet *trp, const struct spool *spool,
int
-null_archive_file (struct file_triplet *trp, const struct spool *spool,
- const char *file_name, const char *reldir)
+null_archive_file (struct file_triplet *trp, const char *file_name)
{
if (debug_level)
- logmsg (LOG_DEBUG, _("spool %s: archiving `%s'"), spool->tag, file_name);
+ logmsg (LOG_DEBUG, _("spool %s: archiving `%s'"),
+ trp->spool->tag, file_name);
UPDATE_STATS (STAT_ARCHIVES);
@@ -47,4 +47,3 @@ null_archive_file (struct file_triplet *trp, const struct spool *spool,
int
-null_symlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir,
+null_symlink_file (struct file_triplet *trp,
const char *wanted_src, const char *wanted_dst)
@@ -53,3 +52,3 @@ null_symlink_file (struct file_triplet *trp, const struct spool *spool,
logmsg (LOG_DEBUG, _("spool %s: symlinking `%s' to `%s'"),
- spool->tag, wanted_src, wanted_dst);
+ trp->spool->tag, wanted_src, wanted_dst);
UPDATE_STATS (STAT_SYMLINKS);
@@ -59,4 +58,3 @@ null_symlink_file (struct file_triplet *trp, const struct spool *spool,
int
-null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name)
+null_rmsymlink_file (struct file_triplet *trp, const char *file_name)
{
@@ -64,3 +62,3 @@ null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
logmsg (LOG_DEBUG, _("spool %s: removing symlink `%s/%s'"),
- spool->tag, reldir, file_name);
+ trp->spool->tag, trp->relative_dir, file_name);
UPDATE_STATS (STAT_RMSYMLINKS);
diff --git a/src/triplet.c b/src/triplet.c
index efe4a0b..ea57a08 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -44,2 +44,3 @@ hash_triplet_free (void *data)
struct file_triplet *tp = data;
+ struct uploader_info *up;
@@ -54,4 +55,11 @@ hash_triplet_free (void *data)
free (tp->tmp);
- free (tp->check_diag);
- /* FIXME: free uploader list */
+ obstack_free (&tp->obstk, NULL);
+
+ /* Free uploader list */
+ for (up = tp->uploader_list; up; )
+ {
+ struct uploader_info *next = up->next;
+ free (up);
+ up = next;
+ }
@@ -60,2 +68,10 @@ hash_triplet_free (void *data)
+char *
+triplet_strdup (struct file_triplet *tp, const char *str)
+{
+ size_t len = strlen (str);
+ obstack_grow (&tp->obstk, str, len + 1);
+ return obstack_finish (&tp->obstk);
+}
+
/* Register a file in the triplet table */
@@ -81,3 +97,5 @@ register_file (struct file_info *finfo, const struct spool *spool)
- if (ret != tp)
+ if (ret == tp)
+ obstack_init (&tp->obstk);
+ else
free (tp);
diff --git a/src/verify.c b/src/verify.c
index 01c61ea..93fd28b 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -95,3 +95,3 @@ fill_project_name (struct file_triplet *trp)
FILE *fp;
- char *project, *p;
+ char *p;
const char *directory;
@@ -152,6 +152,15 @@ fill_project_name (struct file_triplet *trp)
}
- p = strchr (directory, '/');
+
+ trp->relative_dir = safe_file_name (triplet_strdup (trp, directory));
+ if (!trp->relative_dir || trp->relative_dir[0] == '/')
+ {
+ logmsg (LOG_ERR, _("%s: invalid directory: %s"),
+ trp->file[file_directive].name, directory);
+ return 1;
+ }
+
+ p = strchr (trp->relative_dir, '/');
if (p)
{
- size_t len = p - directory;
+ size_t len = p - trp->relative_dir;
if (len == 0)
@@ -162,9 +171,9 @@ fill_project_name (struct file_triplet *trp)
}
- project = xmalloc (len + 1);
- memcpy (project, directory, len);
- project[len] = 0;
+ obstack_grow (&trp->obstk, trp->relative_dir, len);
+ obstack_1grow (&trp->obstk, 0);
+ trp->project = obstack_finish (&trp->obstk);
}
else
- project = xstrdup (directory);
- trp->project = xstrdup (project);
+ trp->project = trp->relative_dir;
+
return 0;
@@ -256,12 +265,12 @@ verify_directive_file (struct file_triplet *trp)
if (p)
- info.name = xstrdup (p);
+ info.name = triplet_strdup (trp, p);
p = dictionary_result (dict, md, i, 1);
if (p)
- info.realname = xstrdup (p);
+ info.realname = triplet_strdup (trp, p);
p = dictionary_result (dict, md, i, 2);
if (p)
- info.email = xstrdup (p);
+ info.email = triplet_strdup (trp, p);
p = dictionary_result (dict, md, i, 3);
if (p)
- info.gpg_key = xstrdup (p);
+ info.gpg_key = triplet_strdup (trp, p);
@@ -280,6 +289,3 @@ verify_directive_file (struct file_triplet *trp)
(unsigned long) i);
- free (info.name);
- free (info.realname);
- free (info.gpg_key);
- free (info.email);
+ /* FIXME: Memory not reclaimed */
continue;
diff --git a/src/vtab.c b/src/vtab.c
index 9854660..918bab3 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -56,7 +56,6 @@ url_to_vtab (mu_url_t url, struct virt_tab *vtab)
int
-move_file (struct file_triplet *trp, const struct spool *spool,
- enum file_type file_id, const char *reldir)
+move_file (struct file_triplet *trp, enum file_type file_id)
{
- int rc = spool->vtab.move_file (trp, spool, file_id, reldir);
- report_add ("Move %s to %s: %s", trp->file[file_id].name, reldir,
+ int rc = trp->spool->vtab.move_file (trp, file_id);
+ report_add ("Move %s to %s: %s", trp->file[file_id].name, trp->relative_dir,
rc == 0 ? "OK" : "FAILED");
@@ -66,7 +65,6 @@ move_file (struct file_triplet *trp, const struct spool *spool,
int
-archive_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name)
+archive_file (struct file_triplet *trp, const char *file_name)
{
- int rc = spool->vtab.archive_file (trp, spool, reldir, file_name);
- report_add ("Archive and remove %s/%s: %s", reldir, file_name,
+ int rc = trp->spool->vtab.archive_file (trp, file_name);
+ report_add ("Archive and remove %s/%s: %s", trp->relative_dir, file_name,
rc == 0 ? "OK" : "FAILED");
@@ -76,10 +74,8 @@ archive_file (struct file_triplet *trp, const struct spool *spool,
int
-symlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir,
+symlink_file (struct file_triplet *trp,
const char *wanted_src, const char *wanted_dst)
{
- int rc = spool->vtab.symlink_file (trp, spool, reldir,
- wanted_src, wanted_dst);
+ int rc = trp->spool->vtab.symlink_file (trp, wanted_src, wanted_dst);
report_add ("Symlink %s to %s in %s/: %s", wanted_src, wanted_dst,
- reldir,
+ trp->relative_dir,
rc == 0 ? "OK" : "FAILED");
@@ -89,7 +85,6 @@ symlink_file (struct file_triplet *trp, const struct spool *spool,
int
-rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name)
+rmsymlink_file (struct file_triplet *trp, const char *file_name)
{
- int rc = spool->vtab.rmsymlink_file (trp, spool, reldir, file_name);
- report_add ("Remove symlink %s/%s: %s", reldir, file_name,
+ int rc = trp->spool->vtab.rmsymlink_file (trp, file_name);
+ report_add ("Remove symlink %s/%s: %s", trp->relative_dir, file_name,
rc == 0 ? "OK" : "FAILED");
diff --git a/src/wydawca.h b/src/wydawca.h
index b44b5d7..da093c3 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -176,2 +176,3 @@ struct file_triplet
const struct spool *spool; /* Owning spool */
+ char *relative_dir; /* Directory relative to spool->dest_dir */
char **directive; /* Decoded directive pairs (key: value\0) */
@@ -180,2 +181,3 @@ struct file_triplet
size_t tmpsize; /* Size of memory allocated in tmp */
+ struct obstack obstk; /* Obstack for string allocation */
/* User data */
@@ -201,19 +203,8 @@ struct virt_tab
int (*test_url) (mu_url_t url, grecs_locus_t *loc);
- int (*move_file) (struct file_triplet *trp,
- const struct spool *spool,
- enum file_type file_id,
- const char *reldir);
- int (*archive_file) (struct file_triplet *trp,
- const struct spool *spool,
- const char *reldir,
- const char *file_name);
+ int (*move_file) (struct file_triplet *trp, enum file_type file_id);
+ int (*archive_file) (struct file_triplet *trp, const char *file_name);
int (*symlink_file) (struct file_triplet *trp,
- const struct spool *spool,
- const char *reldir,
const char *wanted_src,
const char *wanted_dst);
- int (*rmsymlink_file)(struct file_triplet *trp,
- const struct spool *spool,
- const char *reldir,
- const char *file_name);
+ int (*rmsymlink_file)(struct file_triplet *trp, const char *file_name);
};
@@ -468,2 +459,3 @@ int selected_spools (void);
+char *triplet_strdup (struct file_triplet *tp, const char *str);
@@ -484,14 +476,10 @@ int url_to_vtab (mu_url_t url, struct virt_tab *vtab);
int
-move_file (struct file_triplet *trp, const struct spool *spool,
- enum file_type file_id, const char *reldir);
+move_file (struct file_triplet *trp, enum file_type file_id);
int
-archive_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name);
+archive_file (struct file_triplet *trp, const char *file_name);
int
-symlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir,
+symlink_file (struct file_triplet *trp,
const char *wanted_src, const char *wanted_dst);
int
-rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name);
+rmsymlink_file (struct file_triplet *trp, const char *file_name);
@@ -503,22 +491,14 @@ int copy_file (const char *file, const char *dst_file);
int dir_test_url (mu_url_t url, grecs_locus_t *locus);
-int dir_move_file (struct file_triplet *trp, const struct spool *spool,
- enum file_type file_id, const char *reldir);
-int dir_archive_file (struct file_triplet *trp, const struct spool *spool,
- const char *file_name, const char *reldir);
-int dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir,
+int dir_move_file (struct file_triplet *trp, enum file_type file_id);
+int dir_archive_file (struct file_triplet *trp, const char *reldir);
+int dir_symlink_file (struct file_triplet *trp,
const char *wanted_src, const char *wanted_dst);
-int dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name);
+int dir_rmsymlink_file (struct file_triplet *trp, const char *file_name);
/* null.c */
-int null_move_file (struct file_triplet *trp, const struct spool *spool,
- enum file_type file_id, const char *reldir);
-int null_archive_file (struct file_triplet *trp, const struct spool *spool,
- const char *file_name, const char *reldir);
-int null_symlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir,
+int null_move_file (struct file_triplet *trp, enum file_type file_id);
+int null_archive_file (struct file_triplet *trp, const char *file_name);
+int null_symlink_file (struct file_triplet *trp,
const char *wanted_src, const char *wanted_dst);
-int null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
- const char *reldir, const char *file_name);
+int null_rmsymlink_file (struct file_triplet *trp, const char *file_name);

Return to:

Send suggestions and report system problems to the System administrator.