00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <unistd.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <sys/fcntl.h>
00025 #include <errno.h>
00026 #include <getopt.h>
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 static void __attribute__ ((__noreturn__)) usage(char **argv, int err)
00041 {
00042 fprintf(stderr, "\nUsage:\n");
00043 fprintf(stderr, "%s <uevent DEVPATH of SCSI device>\n", argv[0]);
00044 fprintf(stderr, "\nOptions:\n");
00045 fprintf(stderr, " -h, --help display this help and exit\n");
00046 exit(err);
00047 }
00048
00049 static void __attribute__ ((__noreturn__)) invalid(char **argv, char *devpath)
00050 {
00051 fprintf(stderr, "Invalid DEVPATH '%s'.\n", devpath);
00052 usage(argv, 1);
00053 }
00054
00055 int main(int argc, char **argv)
00056 {
00057 char c;
00058 char *devpath;
00059
00060 char *sysfs_path;
00061 char *sysfs_data;
00062 struct stat sysfs_stat;
00063 int fd;
00064
00065 char *host_str;
00066 int host_pos;
00067 int host_len;
00068 char *host_next_str;
00069 int host_next_pos;
00070 int host_next_len;
00071 char *target_str;
00072 int target_pos;
00073 int target_len;
00074
00075 char *channel_str;
00076 int channel_pos;
00077 int channel_len;
00078 char *id_str;
00079 int id_pos;
00080 int id_len;
00081
00082 char *dir_str;
00083
00084 static const struct option longopts[] = {
00085 {"help", no_argument, 0, 'h'},
00086 {NULL, no_argument, 0, '0'},
00087 };
00088
00089
00090 while ((c = getopt_long(argc, argv, "rh", longopts, NULL)) != -1) {
00091 switch (c) {
00092 case 'h':
00093 usage(argv, 0);
00094 default:
00095 usage(argv, 1);
00096 }
00097 }
00098
00099 if (optind >= argc) {
00100 usage(argv, 1);
00101 }
00102 devpath = argv[optind++];
00103
00104
00105
00106
00107
00108
00109 if (devpath == NULL) {
00110 usage(argv, 1);
00111 }
00112
00113 sysfs_path = malloc(strlen("/sys") + strlen(devpath) + 1);
00114 strcpy(sysfs_path, "/sys");
00115 strcat(sysfs_path, devpath);
00116
00117 if (stat(sysfs_path, &sysfs_stat) < 0) {
00118 fprintf(stderr, "Cannot stat '%s': %s\n", sysfs_path, strerror(errno));
00119 usage(argv, 1);
00120 }
00121 if (!S_ISDIR(sysfs_stat.st_mode))
00122 invalid(argv, devpath);
00123
00124 free(sysfs_path);
00125
00126
00127
00128
00129 if ((host_str = strstr(devpath, "/host")) == NULL)
00130 invalid(argv, devpath);
00131 host_pos = strlen(devpath) - strlen(host_str);
00132
00133 if ((host_next_str = strstr(&devpath[host_pos + 1], "/")) == NULL)
00134 invalid(argv, devpath);
00135 host_next_pos = strlen(devpath) - strlen(host_next_str);
00136
00137 if ((target_str = strstr(devpath, "/target")) == NULL)
00138 invalid(argv, devpath);
00139 target_pos = strlen(devpath) - strlen(target_str);
00140
00141 host_len = host_next_pos - host_pos;
00142 if (host_len <= strlen("/host"))
00143 invalid(argv, devpath);
00144
00145 host_next_len = strlen(&devpath[host_next_pos]);
00146 if (host_next_len <= strlen("/"))
00147 invalid(argv, devpath);
00148
00149 target_len = strlen(&devpath[target_pos]);
00150 if (target_len <= strlen("/target"))
00151 invalid(argv, devpath);
00152
00153 sysfs_path = malloc(strlen("/sys") + strlen(devpath) - host_next_len + strlen("/scsi_host") + host_len + strlen("/scan") + 1);
00154
00155 strcpy(sysfs_path, "/sys");
00156 strncat(sysfs_path, devpath, host_next_pos);
00157 strcat(sysfs_path, "/scsi_host");
00158 strncat(sysfs_path, host_str, host_len);
00159 strcat(sysfs_path, "/scan");
00160
00161
00162
00163
00164 if ((channel_str = strstr(&devpath[target_pos], ":")) == NULL)
00165 invalid(argv, devpath);
00166 channel_pos = strlen(&devpath[target_pos]) - strlen(channel_str) + 1;
00167
00168 if ((id_str = strstr(&devpath[target_pos + channel_pos], ":")) == NULL)
00169 invalid(argv, devpath);
00170 id_pos = strlen(&devpath[target_pos + channel_pos]) - strlen(id_str) + 1;
00171
00172 if ((dir_str = strstr(&devpath[target_pos + channel_pos + id_pos], "/")) == NULL)
00173 invalid(argv, devpath);
00174
00175 channel_len = strlen(&devpath[target_pos + channel_pos]) - strlen(id_str);
00176 if (channel_len < 1)
00177 invalid(argv, devpath);
00178
00179 id_len = strlen(&devpath[target_pos + channel_pos + id_pos]) - strlen(dir_str);
00180 if (id_len < 1)
00181 invalid(argv, devpath);
00182
00183 sysfs_data = malloc(channel_len + strlen(" ") + id_len + strlen(" -") + 1);
00184
00185 sysfs_data[0] = '\0';
00186 strncat(sysfs_data, &devpath[target_pos + channel_pos], channel_len);
00187 strcat(sysfs_data, " ");
00188 strncat(sysfs_data, &devpath[target_pos + channel_pos + id_pos], id_len);
00189 strcat(sysfs_data, " -");
00190
00191
00192
00193
00194 if ((fd = open(sysfs_path, O_WRONLY)) < 0) {
00195 fprintf(stderr, "Cannot open '%s': %s\n", sysfs_path, strerror(errno));
00196 usage(argv, 1);
00197 }
00198 if (write(fd, sysfs_data, strlen(sysfs_data)) < 0) {
00199 fprintf(stderr, "Cannot write '%s': %s\n", sysfs_path, strerror(errno));
00200 usage(argv, 1);
00201 }
00202 close(fd);
00203 free(sysfs_path);
00204 free(sysfs_data);
00205 return 0;
00206 }