X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fcfg.c;h=d61cd778f291cc18b421e47aae9c047418b30e9c;hb=6bf4c631ae776f4e936b5f01efe4bfbe190f5d99;hp=b4d1d591a74e8e6188881577dc60fb1c949e0fa5;hpb=064af42167bf4fc9aaea2702d80ce08074b889c0;p=openvswitch
diff --git a/lib/cfg.c b/lib/cfg.c
index b4d1d591..d61cd778 100644
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -1,27 +1,16 @@
/* Copyright (c) 2008, 2009 Nicira Networks
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * In addition, as a special exception, Nicira Networks gives permission
- * to link the code of its release of vswitchd with the OpenSSL project's
- * "OpenSSL" library (or with modified versions of it that use the same
- * license as the "OpenSSL" library), and distribute the linked
- * executables. You must obey the GNU General Public License in all
- * respects for all of the code used other than "OpenSSL". If you modify
- * this file, you may extend this exception to your version of the file,
- * but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#include
@@ -36,10 +25,9 @@
#include
#include
#include
-#include
-#include
#include "coverage.h"
#include "dynamic-string.h"
+#include "lockfile.h"
#include "ofpbuf.h"
#include "packets.h"
#include "svec.h"
@@ -63,8 +51,7 @@ static char *cfg_name;
static char *tmp_name;
/* Lock information. */
-static char *lock_name;
-static int lock_fd = -1;
+static struct lockfile *lockfile;
/* Flag to indicate whether local modifications have been made. */
static bool dirty;
@@ -103,6 +90,12 @@ static bool is_type(const char *s, enum cfg_flags);
#define CC_FILE_NAME CC_ALNUM "._-"
#define CC_KEY CC_ALNUM "._-@$:+"
+void
+cfg_init(void)
+{
+ svec_terminate(&cfg);
+}
+
/* Sets 'file_name' as the configuration file read by cfg_read(). Returns 0 on
* success, otherwise a positive errno value if 'file_name' cannot be opened.
*
@@ -111,15 +104,14 @@ static bool is_type(const char *s, enum cfg_flags);
int
cfg_set_file(const char *file_name)
{
- const char *slash;
+ char *lock_name;
int fd;
if (cfg_name) {
- assert(lock_fd < 0);
+ assert(!lockfile);
free(cfg_name);
- free(lock_name);
free(tmp_name);
- cfg_name = lock_name = tmp_name = NULL;
+ cfg_name = tmp_name = NULL;
}
/* Make sure that we can open this file for reading. */
@@ -136,40 +128,26 @@ cfg_set_file(const char *file_name)
* rename(tmp_name, cfg_name) will work. */
tmp_name = xasprintf("%s.~tmp~", file_name);
- /* Put the lock file in the same directory as cfg_name, but prefixed by
- * a dot so as not to garner administrator interest. */
- slash = strrchr(file_name, '/');
- if (slash) {
- lock_name = xasprintf("%.*s/.%s.~lock~",
- slash - file_name, file_name, slash + 1);
- } else {
- lock_name = xasprintf(".%s.~lock~", file_name);
- }
-
+ lock_name = lockfile_name(file_name);
VLOG_INFO("using \"%s\" as configuration file, \"%s\" as lock file",
file_name, lock_name);
+ free(lock_name);
+
return 0;
}
static int
update_cookie(void)
{
+ struct sha1_ctx context;
int i;
- SHA1Context context;
- if (SHA1Reset(&context) != shaSuccess) {
- return -1;
- }
+ sha1_init(&context);
for (i = 0; i < cfg.n; i++) {
- if (SHA1Input(&context, (uint8_t *)cfg.names[i],
- strlen(cfg.names[i])) != shaSuccess) {
- return -1;
- }
- SHA1Input(&context, (uint8_t *)"\n", 1);
- }
- if (SHA1Result(&context, cfg_cookie) != shaSuccess) {
- return -1;
+ sha1_update(&context, cfg.names[i], strlen(cfg.names[i]));
+ sha1_update(&context, "\n", 1);
}
+ sha1_final(&context, cfg_cookie);
return 0;
}
@@ -201,6 +179,7 @@ cfg_read(void)
file = fopen(cfg_name, "r");
if (!file) {
VLOG_ERR("failed to open \"%s\": %s", cfg_name, strerror(errno));
+ svec_terminate(&cfg);
return errno;
}
@@ -291,54 +270,12 @@ cfg_get_cookie(uint8_t *cookie)
void
cfg_unlock(void)
{
- if (lock_fd != -1) {
- COVERAGE_INC(cfg_unlock);
- close(lock_fd);
- lock_fd = -1;
+ if (lockfile) {
+ lockfile_unlock(lockfile);
+ lockfile = NULL;
}
}
-static int
-open_lockfile(const char *name)
-{
- for (;;) {
- /* Try to open an existing lock file. */
- int fd = open(name, O_RDWR);
- if (fd >= 0) {
- return fd;
- } else if (errno != ENOENT) {
- VLOG_WARN("%s: failed to open lock file: %s",
- name, strerror(errno));
- return -errno;
- }
-
- /* Try to create a new lock file. */
- VLOG_INFO("%s: lock file does not exist, creating", name);
- fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
- if (fd >= 0) {
- return fd;
- } else if (errno != EEXIST) {
- VLOG_WARN("%s: failed to create lock file: %s",
- name, strerror(errno));
- return -errno;
- }
-
- /* Someone else created the lock file. Try again. */
- }
-}
-
-static int
-try_lock(int fd, bool block)
-{
- struct flock l;
- memset(&l, 0, sizeof l);
- l.l_type = F_WRLCK;
- l.l_whence = SEEK_SET;
- l.l_start = 0;
- l.l_len = 0;
- return fcntl(fd, block ? F_SETLKW : F_SETLK, &l) == -1 ? errno : 0;
-}
-
/* Locks the configuration file against modification by other processes and
* re-reads it from disk.
*
@@ -350,62 +287,18 @@ try_lock(int fd, bool block)
int
cfg_lock(uint8_t *cookie, int timeout)
{
- long long int start = time_msec();
- long long int elapsed = 0;
- int fd;
- uint8_t curr_cookie[CFG_COOKIE_LEN];
-
- assert(lock_fd < 0);
- COVERAGE_INC(cfg_lock);
- for (;;) {
- int error;
-
- /* Open lock file. */
- fd = open_lockfile(lock_name);
- if (fd < 0) {
- return -fd;
- }
-
- /* Try to lock it. This will block (if 'timeout' > 0). */
- error = try_lock(fd, timeout > 0);
- time_refresh();
- elapsed = time_msec() - start;
- if (!error) {
- /* Success! */
- break;
- }
-
- /* Lock failed. Close the lock file and reopen it on the next
- * iteration, just in case someone deletes it underneath us (even
- * though that should not happen). */
- close(fd);
- if (error != EINTR) {
- /* Hard error, give up. */
- COVERAGE_INC(cfg_lock_error);
- VLOG_WARN("%s: failed to lock file "
- "(after %lld ms, with %d-ms timeout): %s",
- lock_name, elapsed, timeout, strerror(error));
- return error;
- }
+ int error;
- /* Probably, the periodic timer set up by time_init() woke up us. Just
- * check whether it's time to give up. */
- if (timeout != INT_MAX && elapsed >= timeout) {
- COVERAGE_INC(cfg_lock_timeout);
- VLOG_WARN("%s: giving up on lock file after %lld ms",
- lock_name, elapsed);
- return ETIMEDOUT;
- }
- COVERAGE_INC(cfg_lock_retry);
- }
- if (elapsed) {
- VLOG_WARN("%s: waited %lld ms for lock file", lock_name, elapsed);
+ assert(!lockfile);
+ error = lockfile_lock(cfg_name, timeout, &lockfile);
+ if (error) {
+ return error;
}
- lock_fd = fd;
cfg_read();
if (cookie) {
+ uint8_t curr_cookie[CFG_COOKIE_LEN];
cfg_get_cookie(curr_cookie);
if (memcmp(curr_cookie, cookie, sizeof *curr_cookie)) {
@@ -691,6 +584,25 @@ cfg_del_match(const char *pattern_, ...)
free(pattern);
}
+/* Fills 'svec' with all of the key-value pairs that match shell glob pattern
+ * 'pattern'. The caller must first initialize 'svec'. */
+void
+cfg_get_matches(struct svec *svec, const char *pattern_, ...)
+{
+ char *pattern;
+ char **p;
+
+ FORMAT_KEY(pattern_, pattern);
+
+ for (p = cfg.names; *p; p++) {
+ if (!fnmatch(pattern, *p, 0)) {
+ svec_add(svec, *p);
+ }
+ }
+
+ free(pattern);
+}
+
/* Fills 'svec' with all of the key-value pairs that have sections that
* begin with 'section'. The caller must first initialize 'svec'. */
void
@@ -1116,8 +1028,8 @@ find_key(const char *key)
static bool
parse_mac(const char *s, uint8_t mac[6])
{
- return sscanf(s, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8,
- &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6;
+ return (sscanf(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
+ == ETH_ADDR_SCAN_COUNT);
}
static bool