Use the gcc cleanup extension attribute to handle closing temp files

While some of these allocations will go away as we convert to C++,
some of these need to stay C as the are going to be moved into a
library to support loading cache from init daemons etc.

For the bits that will eventually be C++ this helps clean things up,
in the interim.

TODO: apply to libapparmor as well

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Tyler Hicks <tyhicks@canonical.com>
This commit is contained in:
John Johansen 2015-03-25 17:09:26 -05:00 committed by Tyler Hicks
parent 82904cf0e6
commit f62cc5c6bf
8 changed files with 39 additions and 36 deletions

View file

@ -72,7 +72,8 @@ static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
fst->pos = snprintf_buffer(*fst->buffer, fst->pos, fst->size, "%s {", name); fst->pos = snprintf_buffer(*fst->buffer, fst->pos, fst->size, "%s {", name);
if (S_ISREG(st->st_mode)) { if (S_ISREG(st->st_mode)) {
int len, file; autoclose int file = -1;
int len;
int remaining = fst->size - (fst->pos - *fst->buffer); int remaining = fst->size - (fst->pos - *fst->buffer);
file = openat(dirfd(dir), name, O_RDONLY); file = openat(dirfd(dir), name, O_RDONLY);
@ -98,7 +99,6 @@ static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
PDEBUG("Error reading feature file '%s'\n", name); PDEBUG("Error reading feature file '%s'\n", name);
return -1; return -1;
} }
close(file);
} else if (S_ISDIR(st->st_mode)) { } else if (S_ISDIR(st->st_mode)) {
if (dirat_for_each(dir, name, fst, features_dir_cb)) if (dirat_for_each(dir, name, fst, features_dir_cb))
return -1; return -1;
@ -124,7 +124,7 @@ static char *handle_features_dir(const char *filename, char **buffer, int size,
char *load_features_file(const char *name) { char *load_features_file(const char *name) {
char *buffer; char *buffer;
FILE *f = NULL; autofclose FILE *f = NULL;
size_t size; size_t size;
f = fopen(name, "r"); f = fopen(name, "r");
@ -140,14 +140,11 @@ char *load_features_file(const char *name) {
goto fail; goto fail;
buffer[size] = 0; buffer[size] = 0;
fclose(f);
return buffer; return buffer;
fail: fail:
int save = errno; int save = errno;
free(buffer); free(buffer);
if (f)
fclose(f);
errno = save; errno = save;
return NULL; return NULL;
} }

View file

@ -40,6 +40,23 @@ void __autofree(void *p)
free(*_p); free(*_p);
} }
void __autoclose(int *fd)
{
if (*fd != -1) {
/* if close was interrupted retry */
while(close(*fd) == -1 && errno == EINTR);
*fd = -1;
}
}
void __autofclose(FILE **f)
{
if (*f) {
fclose(*f);
*f = NULL;
}
}
/** /**
* dirat_for_each: iterate over a directory calling cb for each entry * dirat_for_each: iterate over a directory calling cb for each entry
* @dir: already opened directory (MAY BE NULL) * @dir: already opened directory (MAY BE NULL)

View file

@ -4,7 +4,11 @@
#include <dirent.h> #include <dirent.h>
#define autofree __attribute((cleanup(__autofree))) #define autofree __attribute((cleanup(__autofree)))
#define autoclose __attribute((cleanup(__autoclose)))
#define autofclose __attribute((cleanup(__autofclose)))
void __autofree(void *p); void __autofree(void *p);
void __autoclose(int *fd);
void __autofclose(FILE **f);
int dirat_for_each(DIR *dir, const char *name, void *data, int dirat_for_each(DIR *dir, const char *name, void *data,
int (* cb)(DIR *, const char *, struct stat *, void *)); int (* cb)(DIR *, const char *, struct stat *, void *));

View file

@ -25,6 +25,7 @@
#include <sstream> #include <sstream>
#include <map> #include <map>
#include "lib.h"
#include "parser.h" #include "parser.h"
#include "profile.h" #include "profile.h"
#include "parser_yacc.h" #include "parser_yacc.h"
@ -154,7 +155,8 @@ static struct network_tuple network_mappings[] = {
static size_t kernel_af_max(void) { static size_t kernel_af_max(void) {
char buffer[32]; char buffer[32];
int major; int major;
int fd, res; autoclose int fd = -1;
int res;
if (!net_af_max_override) { if (!net_af_max_override) {
return 0; return 0;
@ -168,7 +170,6 @@ static size_t kernel_af_max(void) {
/* fall back to default provided during build */ /* fall back to default provided during build */
return 0; return 0;
res = read(fd, &buffer, sizeof(buffer) - 1); res = read(fd, &buffer, sizeof(buffer) - 1);
close(fd);
if (res <= 0) if (res <= 0)
return 0; return 0;
buffer[res] = '\0'; buffer[res] = '\0';

View file

@ -45,6 +45,8 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>
#include "lib.h"
#include "parser.h" #include "parser.h"
#include "parser_include.h" #include "parser_include.h"
@ -176,7 +178,7 @@ int add_search_dir(const char *dir)
SUBDOMAIN_PATH=/etc/subdomain.d/include */ SUBDOMAIN_PATH=/etc/subdomain.d/include */
void parse_default_paths(void) void parse_default_paths(void)
{ {
FILE *f; autofclose FILE *f;
char buf[1024]; char buf[1024];
char *t, *s; char *t, *s;
int saved_npath = npath; int saved_npath = npath;
@ -202,7 +204,6 @@ void parse_default_paths(void)
} while (s != NULL); } while (s != NULL);
} }
} }
fclose(f);
/* if subdomain.conf doesn't set a base search dir set it to this */ /* if subdomain.conf doesn't set a base search dir set it to this */
out: out:

View file

@ -479,7 +479,7 @@ void sd_serialize_top_profile(std::ostringstream &buf, Profile *profile)
int cache_fd = -1; int cache_fd = -1;
int __sd_serialize_profile(int option, Profile *prof) int __sd_serialize_profile(int option, Profile *prof)
{ {
int fd = -1; autoclose int fd = -1;
int error = -ENOMEM, size, wsize; int error = -ENOMEM, size, wsize;
std::ostringstream work_area; std::ostringstream work_area;
autofree char *filename = NULL; autofree char *filename = NULL;
@ -594,9 +594,6 @@ int __sd_serialize_profile(int option, Profile *prof)
} }
} }
if (fd != -1)
close(fd);
if (!prof->hat_table.empty() && option != OPTION_REMOVE) { if (!prof->hat_table.empty() && option != OPTION_REMOVE) {
if (load_flattened_hats(prof, option) == 0) if (load_flattened_hats(prof, option) == 0)
return 0; return 0;
@ -641,7 +638,7 @@ static int write_buffer(int fd, char *buffer, int size, bool set)
int sd_load_buffer(int option, char *buffer, int size) int sd_load_buffer(int option, char *buffer, int size)
{ {
int fd = -1; autoclose int fd = -1;
int error, bsize; int error, bsize;
autofree char *filename = NULL; autofree char *filename = NULL;
@ -666,8 +663,7 @@ int sd_load_buffer(int option, char *buffer, int size)
if (fd < 0) { if (fd < 0) {
PERROR(_("Unable to open %s - %s\n"), filename, PERROR(_("Unable to open %s - %s\n"), filename,
strerror(errno)); strerror(errno));
error = -errno; return -errno;
goto out;
} }
if (kernel_supports_setload) { if (kernel_supports_setload) {
@ -688,8 +684,6 @@ int sd_load_buffer(int option, char *buffer, int size)
break; break;
} }
} }
close(fd);
out:
return error; return error;
} }

View file

@ -498,7 +498,7 @@ static int process_args(int argc, char *argv[])
static int process_config_file(const char *name) static int process_config_file(const char *name)
{ {
char *optarg; char *optarg;
FILE *f; autofclose FILE *f = NULL;
int c, o; int c, o;
f = fopen(name, "r"); f = fopen(name, "r");
@ -507,7 +507,6 @@ static int process_config_file(const char *name)
while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1) while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1)
process_arg(c, optarg); process_arg(c, optarg);
fclose(f);
return 1; return 1;
} }
@ -553,7 +552,7 @@ int have_enough_privilege(void)
static void set_features_by_match_file(void) static void set_features_by_match_file(void)
{ {
FILE *ms = fopen(MATCH_FILE, "r"); autofclose FILE *ms = fopen(MATCH_FILE, "r");
if (ms) { if (ms) {
autofree char *match_string = (char *) malloc(1000); autofree char *match_string = (char *) malloc(1000);
if (!match_string) if (!match_string)
@ -563,14 +562,10 @@ static void set_features_by_match_file(void)
if (strstr(match_string, " perms=c")) if (strstr(match_string, " perms=c"))
perms_create = 1; perms_create = 1;
kernel_supports_network = 1; kernel_supports_network = 1;
goto out; return;
} }
no_match: no_match:
perms_create = 1; perms_create = 1;
out:
if (ms)
fclose(ms);
} }
static void set_supported_features(void) { static void set_supported_features(void) {
@ -618,7 +613,7 @@ int process_binary(int option, const char *profilename)
autofree char *buffer = NULL; autofree char *buffer = NULL;
int retval = 0, size = 0, asize = 0, rsize; int retval = 0, size = 0, asize = 0, rsize;
int chunksize = 1 << 14; int chunksize = 1 << 14;
int fd; autoclose int fd = -1;
if (profilename) { if (profilename) {
fd = open(profilename, O_RDONLY); fd = open(profilename, O_RDONLY);
@ -648,8 +643,6 @@ int process_binary(int option, const char *profilename)
size += rsize; size += rsize;
} while (rsize > 0); } while (rsize > 0);
close(fd);
if (rsize == 0) if (rsize == 0)
retval = sd_load_buffer(option, buffer, size); retval = sd_load_buffer(option, buffer, size);
else else

View file

@ -40,13 +40,12 @@ const char header_string[] = "\004\010\000version\000\002";
bool valid_cached_file_version(const char *cachename) bool valid_cached_file_version(const char *cachename)
{ {
char buffer[16]; char buffer[16];
FILE *f; autofclose FILE *f;
if (!(f = fopen(cachename, "r"))) { if (!(f = fopen(cachename, "r"))) {
PERROR(_("Error: Could not read cache file '%s', skipping...\n"), cachename); PERROR(_("Error: Could not read cache file '%s', skipping...\n"), cachename);
return false; return false;
} }
size_t res = fread(buffer, 1, 16, f); size_t res = fread(buffer, 1, 16, f);
fclose(f);
if (res < 16) { if (res < 16) {
if (debug_cache) if (debug_cache)
pwarn("%s: cache file '%s' invalid size\n", progname, cachename); pwarn("%s: cache file '%s' invalid size\n", progname, cachename);
@ -111,7 +110,7 @@ int clear_cache_files(const char *path)
int create_cache(const char *cachedir, const char *path, const char *features) int create_cache(const char *cachedir, const char *path, const char *features)
{ {
struct stat stat_file; struct stat stat_file;
FILE * f = NULL; autofclose FILE * f = NULL;
if (clear_cache_files(cachedir) != 0) if (clear_cache_files(cachedir) != 0)
goto error; goto error;
@ -122,9 +121,6 @@ create_file:
if (fwrite(features, strlen(features), 1, f) != 1 ) if (fwrite(features, strlen(features), 1, f) != 1 )
goto error; goto error;
fclose(f);
return 0; return 0;
} }