unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / io / usb / slave / v2_0 / host / usbchmod.c
1 //=================================================================
2 //
3 //        usb_chmod.c
4 //
5 //        A utility to manipulate /proc/bus/usb access rights
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // The Linux kernel allows raw access to USB devices via /proc/bus/usb.
44 // However, such access requires root privileges: this makes perfect
45 // sense for typical USB devices, but gets in the way of eCos USB
46 // testing. This utility runs suid and can be used to change the access
47 // rights to a specific and validated USB device.
48 //
49 // Author(s):     bartv
50 // Date:          2001-07-18
51 //####DESCRIPTIONEND####
52 //==========================================================================
53
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <limits.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <errno.h>
60 #include <string.h>
61
62 // Note: this code is duplicated in usbhost.c. Any changes here
63 // should be propagated. For now the routine is too small to warrant
64 // a separate source file.
65 #define USB_ROOT        "/proc/bus/usb/"
66 #define PRODUCT_STRING  "Red Hat eCos USB test"
67
68 static int
69 usb_scan_devices(int* bus, int* dev)
70 {
71     FILE*       devs_file       = fopen(USB_ROOT "devices", "r");
72     int         current_bus     = -1;
73     int         current_dev     = -1;
74     int         ch;
75     
76     if (NULL == devs_file) {
77         fprintf(stderr, "Error: unable to access " USB_ROOT "devices\n");
78         return 0;
79     }
80     ch = getc(devs_file);
81     while (EOF != ch) {
82         if ('T' == ch) {
83             if (2 !=fscanf(devs_file, ":  Bus=%d %*[^D\n]Dev#=%d", &current_bus, &current_dev)) { 
84                 current_bus = -1;
85                 current_dev = -1;
86             }
87         } else if ('S' == ch) {
88             int start = 0, end = 0;
89             if (EOF != fscanf(devs_file, ":  Product=%n" PRODUCT_STRING "%n", &start, &end)) {
90                 if (start < end) {
91                     *bus = current_bus;
92                     *dev = current_dev;
93                     break;
94                 }
95             } 
96         }
97         // Move to the end of the current line.
98         while ((EOF != ch) && ('\n' != ch)) {
99             ch = getc(devs_file);
100         }
101         if (EOF != ch) {
102             ch = getc(devs_file);
103         }
104     }
105     
106     fclose(devs_file);
107     if ((-1 != *bus) && (-1 != *dev)) {
108         return 1;
109     }
110     fprintf(stderr, "Error: failed to find a USB device \"" PRODUCT_STRING "\"\n");
111     return 0;
112 }
113
114 int
115 main(int argc, char** argv)
116 {
117     int         bus, dev;
118     int         actual_bus, actual_dev;
119     char        devname[_POSIX_PATH_MAX];
120     long        strtol_tmp1;
121     char*       strtol_tmp2;
122     
123     if (3 != argc) {
124         fprintf(stderr, "usb_chmod: wrong number of arguments\n");
125         fprintf(stderr, "         : usage, usb_chmod <bus> <dev>\n");
126         exit(EXIT_FAILURE);
127     }
128     if (('\0' == argv[1][0]) || ('\0' == argv[2][0])) {
129         fprintf(stderr, "usb_chmod: invalid arguments\n");
130         exit(EXIT_FAILURE);
131     }
132                                  
133     strtol_tmp1 = strtol(argv[1], &strtol_tmp2, 10);
134     if ('\0' != *strtol_tmp2) {
135         fprintf(stderr, "usbchmod: invalid first argument, not a number\n");
136         exit(EXIT_FAILURE);
137     }
138     if (strtol_tmp1 > INT_MAX) {
139         fprintf(stderr, "usbchmod: invalid first argument, number too large\n");
140         exit(EXIT_FAILURE);
141     }
142     bus = (int) strtol_tmp1;
143
144     strtol_tmp1 = strtol(argv[2], &strtol_tmp2, 10);
145     if ('\0' != *strtol_tmp2) {
146         fprintf(stderr, "usbchmod: invalid second argument, not a number\n");
147         exit(EXIT_FAILURE);
148     }
149     if (strtol_tmp1 > INT_MAX) {
150         fprintf(stderr, "usbchmod: invalid second argument, number too large\n");
151         exit(EXIT_FAILURE);
152     }
153     dev = (int) strtol_tmp1;
154         
155     if (!usb_scan_devices(&actual_bus, &actual_dev)) {
156         fprintf(stderr, "usb_chmod: failed to find eCos USB test application\n");
157         exit(EXIT_FAILURE);
158     }
159     if ((bus != actual_bus) || (dev != actual_dev)) {
160         fprintf(stderr, "usbchmod: mismatch between specified and actual USB identifiers.\n");
161         fprintf(stderr, "         : eCos test application is at %03d/%03d, not %03d/%03d\n",
162                 actual_bus, actual_dev, bus, dev);
163         exit(EXIT_FAILURE);
164     }
165     
166     if (_POSIX_PATH_MAX == snprintf(devname, _POSIX_PATH_MAX, "/proc/bus/usb/" "%03d/%03d", actual_bus, actual_dev)) {
167         fprintf(stderr, "usbchmod: internal error, buffer overflow\n");
168         exit(EXIT_FAILURE);
169     }
170
171     if (0 != chmod(devname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) {
172         int old_errno = errno;
173         fprintf(stderr, "usbchmod: failed to modify access rights on %s\n", devname);
174         fprintf(stderr, "         : %s\n", strerror(old_errno));
175         exit(EXIT_FAILURE);
176     }
177
178     return EXIT_SUCCESS;
179 }