File 1099-add-path_compat_id-to-provide-backwards-compatibility.patch of Package systemd.1059

Index: systemd-210/Makefile.am
===================================================================
--- systemd-210.orig/Makefile.am
+++ systemd-210/Makefile.am
@@ -2807,6 +2807,17 @@ udevlibexec_PROGRAMS += \
 	ata_id
 
 # ------------------------------------------------------------------------------
+path_id_compat_SOURCES = \
+	src/udev/path_id_compat/path_id_compat.c
+
+path_id_compat_LDADD = \
+	libudev-internal.la \
+	libsystemd-shared.la
+
+udevlibexec_PROGRAMS += \
+	path_id_compat
+
+# ------------------------------------------------------------------------------
 cdrom_id_SOURCES = \
 	src/udev/cdrom_id/cdrom_id.c
 
Index: systemd-210/src/udev/path_id_compat/path_id_compat.c
===================================================================
--- /dev/null
+++ systemd-210/src/udev/path_id_compat/path_id_compat.c
@@ -0,0 +1,244 @@
+/*
+ * path_id_compat.c: compose persistent device path (compat version)
+ *
+ * Copyright (C) 2009 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * Logic based on Hannes Reinecke's shell script.
+ *
+ * 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 2 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include "libudev.h"
+
+#define PATH_SIZE	16384
+#define SYSFS_PATH	"/sys"
+
+static int path_prepend(char **path, const char *fmt, ...)
+{
+	va_list va;
+	char *old;
+	char *pre;
+	int err;
+
+	old = *path;
+
+	va_start(va, fmt);
+	err = vasprintf(&pre, fmt, va);
+	va_end(va);
+	if (err < 0)
+		return err;
+
+	if (old != NULL) {
+		err = asprintf(path, "%s-%s", pre, old);
+		if (err < 0)
+			return err;
+		free(pre);
+	} else {
+		*path = pre;
+	}
+
+	free(old);
+	return 0;
+}
+
+static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys)
+{
+	struct udev_device *parent = dev;
+
+	while (parent != NULL) {
+		const char *subsystem;
+
+		subsystem = udev_device_get_subsystem(parent);
+		if (subsystem == NULL || strcmp(subsystem, subsys) != 0)
+			break;
+		dev = parent;
+		parent = udev_device_get_parent(parent);
+	}
+	return dev;
+}
+
+static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path)
+{
+	struct udev_device *hostdev;
+	int host, bus, target, lun;
+	const char *name;
+	char *base;
+	char *pos;
+	DIR *dir;
+	struct dirent *dent;
+	int basenum;
+
+	hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
+	if (hostdev == NULL)
+		return NULL;
+
+	name = udev_device_get_sysname(parent);
+	if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4)
+		return NULL;
+
+	/* rebase host offset to get the local relative number */
+	basenum = -1;
+	base = strdup(udev_device_get_syspath(hostdev));
+	if (base == NULL)
+		return NULL;
+	pos = strrchr(base, '/');
+	if (pos == NULL) {
+		parent = NULL;
+		goto out;
+	}
+	pos[0] = '\0';
+	dir = opendir(base);
+	if (dir == NULL) {
+		parent = NULL;
+		goto out;
+	}
+	for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+		char *rest;
+		int i;
+
+		if (dent->d_name[0] == '.')
+			continue;
+		if (dent->d_type != DT_DIR && dent->d_type != DT_LNK)
+			continue;
+		if (strncmp(dent->d_name, "host", 4) != 0)
+			continue;
+		i = strtoul(&dent->d_name[4], &rest, 10);
+		if (rest[0] != '\0')
+			continue;
+		if (basenum == -1 || i < basenum)
+			basenum = i;
+	}
+	closedir(dir);
+	if (basenum == -1) {
+		parent = NULL;
+		goto out;
+	}
+	host -= basenum;
+
+	path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun);
+out:
+	free(base);
+	return hostdev;
+}
+
+static struct udev_device *handle_ata(struct udev_device *parent, char **path)
+{
+	struct udev_device *hostdev;
+	int host, bus, target, lun;
+	const char *name;
+
+	hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
+	if (hostdev == NULL)
+		return NULL;
+
+	name = udev_device_get_sysname(parent);
+	if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4)
+		return NULL;
+
+	path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun);
+out:
+	return hostdev;
+}
+
+static struct udev_device *handle_scsi(struct udev_device *parent, char **path)
+{
+	const char *devtype;
+	const char *name;
+
+	devtype = udev_device_get_devtype(parent);
+	if (devtype == NULL || strcmp(devtype, "scsi_device") != 0)
+		return parent;
+
+	/* lousy scsi sysfs does not have a "subsystem" for the transport */
+	name = udev_device_get_syspath(parent);
+
+	if (strstr(name, "/ata") != NULL) {
+		parent = handle_ata(parent, path);
+		goto out;
+	}
+
+	parent = handle_scsi_default(parent, path);
+out:
+	return parent;
+}
+
+int main(int argc, char **argv)
+{
+	struct udev *udev;
+	struct udev_device *dev;
+	struct udev_device *parent;
+	char syspath[PATH_SIZE];
+	char *path = NULL;
+	int rc = 1;
+
+	if (argv[1] == NULL) {
+		fprintf(stderr, "No device specified\n");
+		rc = 2;
+		goto exit2;
+	}
+
+	udev = udev_new();
+	if (udev == NULL)
+		goto exit2;
+
+	snprintf(syspath, PATH_SIZE, "%s%s", SYSFS_PATH, argv[1]);
+	dev = udev_device_new_from_syspath(udev, syspath);
+	if (dev == NULL) {
+		fprintf(stderr, "unable to access '%s'\n", argv[1]);
+		rc = 3;
+		goto exit1;
+	}
+
+	/* walk up the chain of devices and compose path */
+	parent = dev;
+	while (parent != NULL) {
+		const char *subsys;
+
+		subsys = udev_device_get_subsystem(parent);
+
+		if (subsys == NULL) {
+			;
+		} else if (strcmp(subsys, "scsi") == 0) {
+			parent = handle_scsi(parent, &path);
+		} else if (strcmp(subsys, "pci") == 0) {
+			path_prepend(&path, "pci-%s", udev_device_get_sysname(parent));
+			parent = skip_subsystem(parent, "pci");
+		}
+
+		parent = udev_device_get_parent(parent);
+	}
+
+	if (path != NULL) {
+		printf("ID_PATH_COMPAT=%s\n", path);
+		free(path);
+		rc = 0;
+	}
+
+	udev_device_unref(dev);
+
+exit1:
+	udev_unref(udev);
+
+exit2:
+	return rc;
+}
Index: systemd-210/rules/60-persistent-storage.rules
===================================================================
--- systemd-210.orig/rules/60-persistent-storage.rules
+++ systemd-210/rules/60-persistent-storage.rules
@@ -64,6 +64,11 @@ ENV{DEVTYPE}=="disk", DEVPATH!="*/virtua
 ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
 ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
 
+# by-path (parent device path, compat version, only for ATA bus)
+ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", DEVPATH!="*/virtual/*", IMPORT{program}="path_id_compat %p"
+ENV{DEVTYPE}=="disk", ENV{ID_PATH_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_COMPAT}"
+ENV{DEVTYPE}=="partition", ENV{ID_PATH_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_COMPAT}-part%n"
+
 # skip unpartitioned removable media devices from drivers which do not send "change" events
 ENV{DEVTYPE}=="disk", KERNEL!="sd*|sr*", ATTR{removable}=="1", GOTO="persistent_storage_end"
 
openSUSE Build Service is sponsored by