device-private.c revision d854ba50a82f28b776c670d27156f0e9881fde8a
/***
This file is part of systemd.
Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
Copyright 2014 Tom Gundersen <teg@jklm.no>
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <ctype.h>
#include "util.h"
#include "macro.h"
#include "refcnt.h"
#include "path-util.h"
#include "strxcpyx.h"
#include "fileio.h"
#include "hashmap.h"
#include "set.h"
#include "strv.h"
#include "mkdir.h"
#include "sd-device.h"
#include "device-util.h"
#include "device-internal.h"
#include "device-private.h"
int r;
if (r < 0)
return r;
if (key[0] != '.') {
if (r < 0)
return r;
}
return 0;
}
char *value;
if (!key)
return -ENOMEM;
if (!value)
return -EINVAL;
*value = '\0';
}
char *path;
int r;
switch (key) {
case 'S':
if (r < 0)
return r;
break;
case 'L':
if (r < 0)
return r;
break;
case 'E':
if (r < 0)
return r;
break;
case 'G':
if (r < 0)
return r;
break;
case 'W':
if (r < 0)
return r;
break;
case 'I':
if (r < 0)
return r;
break;
default:
}
return 0;
}
}
device->is_initialized = true;
}
int r;
else
if (r < 0)
return -errno;
if (r < 0)
return r;
return 0;
}
char *path;
char key;
unsigned i;
int r;
enum {
KEY,
return 0;
if (r < 0)
return r;
if (r < 0) {
if (r == -ENOENT)
return 0;
else {
return r;
}
}
/* devices with a database entry are initialized */
for (i = 0; i < db_len; i++) {
switch (state) {
case PRE_KEY:
}
break;
case KEY:
if (db[i] != ':') {
} else {
db[i] = '\0';
}
break;
case PRE_VALUE:
break;
case INVALID_LINE:
break;
case VALUE:
db[i] = '\0';
if (r < 0)
}
break;
default:
assert_not_reached("invalid state when parsing db");
}
}
return 0;
}
return device->properties_generation;
}
return device->tags_generation;
}
return device->devlinks_generation;
}
int r;
r = device_read_db(device);
if (r < 0)
return r;
return 0;
}
int r;
r = device_read_db(device);
if (r < 0)
return r;
return 0;
}
unsigned u;
int r;
if (r < 0)
return r;
if (r < 0)
return r;
return 0;
}
int r;
r = device_read_db(device);
if (r < 0)
return r;
return 0;
}
unsigned g;
int r;
if (r < 0)
return r;
if (r < 0)
return r;
return 0;
}
int r;
char *path;
/* the caller must verify or trust this data (e.g., if it comes from the kernel) */
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
if (r < 0)
size_t l;
char devlink[l + 1];
devlink[l] = '\0';
if (r < 0)
}
size_t l;
char tag[l + 1];
tag[l] = '\0';
if (r < 0)
}
} else {
if (r < 0)
}
return 0;
}
static const char* const device_action_table[_DEVICE_ACTION_MAX] = {
[DEVICE_ACTION_ADD] = "add",
[DEVICE_ACTION_REMOVE] = "remove",
[DEVICE_ACTION_CHANGE] = "change",
[DEVICE_ACTION_MOVE] = "move",
[DEVICE_ACTION_ONLINE] = "online",
[DEVICE_ACTION_OFFLINE] = "offline",
};
static int device_append(sd_device *device, char *key, const char **_major, const char **_minor, uint64_t *_seqnum,
DeviceAction *_action) {
char *value;
int r;
if (!value) {
return -EINVAL;
}
*value = '\0';
value++;
else {
if (action == _DEVICE_ACTION_INVALID)
return -EINVAL;
if (r < 0)
return r;
else if (seqnum == 0)
/* kernel only sends seqnum > 0 */
return -EINVAL;
}
if (r < 0)
return r;
}
if (major != 0)
if (minor != 0)
if (action != _DEVICE_ACTION_INVALID)
if (seqnum > 0)
return 0;
}
}
log_debug("sd-device: device created from strv lacks devpath, subsystem, action or seqnum");
return -EINVAL;
}
return 0;
}
char **key;
int r;
r = device_new_aux(&device);
if (r < 0)
return r;
if (r < 0)
return r;
}
if (major) {
if (r < 0)
}
if (r < 0)
return r;
return 0;
}
unsigned i = 0;
int r;
r = device_new_aux(&device);
if (r < 0)
return r;
while (i < len) {
char *key;
const char *end;
if (!end) {
log_debug("sd-device: failed to parse nulstr");
return -EINVAL;
}
if (r < 0)
return r;
}
if (major) {
if (r < 0)
}
if (r < 0)
return r;
return 0;
}
size_t allocated_nulstr = 0;
if (!device->properties_buf_outdated)
return 0;
if (!buf_nulstr)
return -ENOMEM;
++num;
}
/* build strv from buf_nulstr */
i = 0;
i++;
}
device->properties_buf_outdated = false;
return 0;
}
int r;
if (r < 0)
return r;
return 0;
}
int r;
if (r < 0)
return r;
return 0;
}
int r;
r = device_read_db(device);
if (r < 0)
return r;
return 0;
}
int r;
r = device_read_db(device);
if (r < 0)
return r;
return 0;
}
}
char *new_syspath;
const char *interface;
int r;
if (!dirname)
return -ENOMEM;
/* the user must trust that the new name is correct */
if (r < 0)
return r;
if (r >= 0) {
if (r < 0)
return r;
/* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
if (r < 0)
return r;
} else if (r != -ENOENT)
return r;
return 0;
}
int r;
r = device_new_aux(&ret);
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
*new_device = ret;
return 0;
}
int r;
if (r < 0)
return r;
r = device_read_db(ret);
if (r < 0)
return r;
*new_device = ret;
return 0;
}
int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
int r;
if (r < 0)
return r;
r = device_read_uevent_file(ret);
if (r < 0)
return r;
if (r < 0)
return r;
*new_device = ret;
return 0;
}
int r;
if (r < 0)
return r;
}
return 0;
}
device->property_tags_outdated = true;
device->tags_generation ++;
}
device->property_devlinks_outdated = true;
}
device->property_tags_outdated = true;
device->tags_generation ++;
}
const char *id;
char *path;
int r;
if (r < 0)
return r;
if (add) {
if (r < 0)
return r;
} else {
return -errno;
}
return 0;
}
const char *tag;
int r = 0, k;
if (add && device_old) {
/* delete possible left-over tags */
if (r >= 0 && k < 0)
r = k;
}
}
}
if (r >= 0 && k < 0)
r = k;
}
return r;
}
return true;
if (device->devlink_priority != 0)
return true;
return true;
return true;
if (device->watch_handle >= 0)
return true;
return false;
}
device->db_persist = true;
}
const char *id;
char *path;
bool has_info;
int r;
if (r < 0)
return r;
/* do not store anything for otherwise empty devices */
return -errno;
return 0;
}
/* write a database file */
if (r < 0)
return r;
if (r < 0)
return r;
/*
* set 'sticky' bit to indicate that we should not clean the
* database when we transition from initramfs to the real root
*/
if (device->db_persist) {
if (r < 0) {
r = -errno;
goto fail;
}
} else {
if (r < 0) {
r = -errno;
goto fail;
}
}
if (has_info) {
Iterator i;
const char *devlink;
if (device->devlink_priority != 0)
if (device->watch_handle >= 0)
}
if (device->usec_initialized > 0)
}
r = fflush_and_check(f);
if (r < 0)
goto fail;
if (r < 0) {
r = -errno;
goto fail;
}
return 0;
fail:
return r;
}
const char *id;
char *path;
int r;
if (r < 0)
return r;
return -errno;
return 0;
}
return device_read_db_aux(device, true);
}