100-svn_update.patch 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264
  1. diff -urN -x .svn hotplug2-0.9/AUTHORS hotplug2/AUTHORS
  2. --- hotplug2-0.9/AUTHORS 2006-10-08 18:13:50.000000000 +0200
  3. +++ hotplug2/AUTHORS 2007-06-30 12:59:20.459674000 +0200
  4. @@ -1,7 +1,11 @@
  5. Authors:
  6. ----------
  7. iSteve <[email protected]>
  8. -Tomas Janousek <[email protected]>
  9. +
  10. + Contributions:
  11. +----------------
  12. +nbd (rules override patch, various fixes, suggestions, testing etc.)
  13. +Tomas Janousek <[email protected]> (Makefiles, SVN hosting)
  14. Thanks to:
  15. ------------
  16. @@ -10,5 +14,9 @@
  17. Randy Dunlap (help with isapnpmap)
  18. Igor2 (provided testing machines)
  19. yanek (provided testing machines)
  20. +Zdenek Styblik (provided testing OpenWRT device)
  21. +OpenWRT team (for trusting this project)
  22. +mtu (debugging, testing, ideas)
  23. +mnemoc (trivial sanity changes on makefiles, linux24 compat patches)
  24. -...anyone taking more than a short peek at the software.
  25. \ No newline at end of file
  26. +...anyone taking more than a short peek at the software.
  27. diff -urN -x .svn hotplug2-0.9/Changelog hotplug2/Changelog
  28. --- hotplug2-0.9/Changelog 2006-10-08 15:32:31.000000000 +0200
  29. +++ hotplug2/Changelog 2007-07-09 01:17:14.865503750 +0200
  30. @@ -1,3 +1,13 @@
  31. +0.9 - 1.0:
  32. +* Add --set-rules-file.
  33. +* Allow any ACTION.
  34. +* Add 'printdebug' rule.
  35. +* Fix chmod, chown, chgrp.
  36. +* Use octal for chmod and makedev.
  37. +* Add 'nothrottle' flag, allowing overriding max-children from a rule
  38. +* Various bugfixes
  39. +* Code comments
  40. +
  41. 0.8 - 0.9:
  42. * Use signals to handle children.
  43. * Separate info and debugging output.
  44. @@ -44,4 +54,4 @@
  45. * Add more actions.
  46. * Significant cleanup of rules handling.
  47. * Better error reporting.
  48. -
  49. \ No newline at end of file
  50. +
  51. diff -urN -x .svn hotplug2-0.9/common.mak hotplug2/common.mak
  52. --- hotplug2-0.9/common.mak 2006-09-26 01:03:08.000000000 +0200
  53. +++ hotplug2/common.mak 2007-07-09 01:17:14.869504000 +0200
  54. @@ -1,6 +1,6 @@
  55. # vim:set sw=8 nosta:
  56. -CFLAGS=-Os -DHAVE_RULES -Wall -g
  57. +CFLAGS=-Os -DHAVE_RULES -Wall -g -Wextra
  58. LDFLAGS=-g
  59. INSTALL=install -c -m 644
  60. @@ -10,7 +10,7 @@
  61. .PHONY: all clean dep install install-recursive clean-recursive \
  62. dep-recursive all-recursive
  63. -MAKEDEP=-gcc $(CFLAGS) -MM $(wildcard *.c *.cc) > .depend
  64. +MAKEDEP=-$(CC) $(CFLAGS) -MM $(wildcard *.c *.cc) > .depend
  65. dep: dep-recursive
  66. $(MAKEDEP)
  67. .depend:
  68. diff -urN -x .svn hotplug2-0.9/docs/hotplug2.8 hotplug2/docs/hotplug2.8
  69. --- hotplug2-0.9/docs/hotplug2.8 2006-09-26 09:23:36.000000000 +0200
  70. +++ hotplug2/docs/hotplug2.8 2007-06-28 14:50:59.874955160 +0200
  71. @@ -22,6 +22,8 @@
  72. .TP
  73. \fB\-\-dumb\fR, \fB\-\-no\-dumb\fR
  74. Run or do not run hotplug2 in dumb mode. Dumb mode means that rules are being ignored, the only action taken is mload modules to all devices whose uevent exports MODALIAS. Only available if compiled with HAVE_RULES.
  75. +\fB\-\-override\fR, \fB\-\-no\-override\fR
  76. +Allows hotplug2 behavior overriding for different rules, using various flags. See hotplug2 rules documentation for details. The default is not to allow overriding, the flags are therefore ignored.
  77. .TP
  78. \fB\-\-max\-children <value>\fR
  79. Set the value of maximum children hotplug2 may have running simultaneously. Default is 20.
  80. @@ -31,6 +33,8 @@
  81. .TP
  82. \fB\-\-set\-modprobe\-cmd <cmd>\fR
  83. Sets the application used to perform modprobe. It only gets used in dumb mode. Default is to autodetect: if '/bin/modprobe' is from module\-init\-tools, use '/sbin/modprobe', otherwise use '/sbin/hotplug2\-modwrap'.
  84. +\fB\-\-set\-rules\-file <file>\fR
  85. +Sets the path to the file containing hotplug2 rules.
  86. .SH "SIGNALS"
  87. .TP
  88. \fBSIGUSR1\fR
  89. diff -urN -x .svn hotplug2-0.9/docs/hotplug2.rules.doc hotplug2/docs/hotplug2.rules.doc
  90. --- hotplug2-0.9/docs/hotplug2.rules.doc 2006-09-26 10:19:46.000000000 +0200
  91. +++ hotplug2/docs/hotplug2.rules.doc 2007-06-28 14:50:59.872955464 +0200
  92. @@ -11,12 +11,12 @@
  93. [... [...]]
  94. }
  95. -Comments are allowed, they are prefixed with '#', treating the whole rest of the
  96. -line as comment. Please note that comments in place of action parameters are not
  97. -supported.
  98. +Comments are allowed, they are prefixed with '#', treating the whole rest of
  99. +the line as comment. Please note that comments in place of action parameters
  100. +are not supported.
  101. -The <key> is one of the environmental variables that have been obtained by the
  102. -uevent netlink.
  103. +The <key> is one of the environmental variables that have been obtained by
  104. +the uevent netlink.
  105. COMMON KEYS
  106. -----------
  107. @@ -66,9 +66,9 @@
  108. -------
  109. * run <...>
  110. - Execute an application using system();, takes one parameter. Note that
  111. - the application has set all environmental variables read by uevent
  112. - netlink.
  113. + Execute an application using system();, takes one parameter. Note
  114. + that the application has set all environmental variables read by
  115. + uevent netlink.
  116. * break
  117. Break the processing of the current block of actions.
  118. @@ -86,23 +86,22 @@
  119. * exec <application [parameter [parameter [...]]]> ;
  120. Execute an application. Takes variable number of parameters, but the
  121. - last parameter must be terminated with semicolon. Again, all variables
  122. - are set as environmental.
  123. + last parameter must be terminated with semicolon. Again, all
  124. + variables are set as environmental.
  125. - If you need to escape the ';', use '\\;'. Only applies for actions with
  126. - variable number of parameters.
  127. + If you need to escape the ';', use '\\;'. Only applies for actions
  128. + with variable number of parameters.
  129. * makedev <path> <mode>
  130. - Create a device with given mode. The mode is not in octal unless it
  131. - starts with '0', eg. "0644" != "644".
  132. + Create a device with given mode. Mode is interpreted as octal.
  133. Major, minor and devpath must be set for makedev to be able to work.
  134. Tests for these variables are also performed internally in makedev
  135. function.
  136. * symlink <target> <linkname>
  137. - Create a symbolic link (symlink, also known as soft link) pointing at
  138. - target with name linkname.
  139. + Create a symbolic link (symlink, also known as soft link) pointing
  140. + at target with name linkname.
  141. * chown <path> <owner name>
  142. Change owner of path to owner name.
  143. @@ -111,12 +110,32 @@
  144. Change group of path to group name.
  145. * chmod <path> <mode>
  146. - Change mode of path to given mode. Like with makedev, heading '0' is
  147. - necessary for the mode to be interpreted as octal.
  148. + Change mode of path to given mode. Mode is interpreted as octal.
  149. * setenv <key> <value>
  150. Sets environmental variable key to the given value. If an env var
  151. of the given name already exists, it gets overwritten.
  152. +
  153. + * printdebug
  154. + Prints all variables read from kernel.
  155. +
  156. + FLAGS
  157. + -----
  158. +
  159. +Flags are, syntactically, just like actions; their semantical value is different however.
  160. +Instead of doing something, they instead change the general behavior of the processing
  161. +of the given rule.
  162. +
  163. +Note that for flags to work, you also have to invoke it with --override.
  164. +
  165. +Currently, only one flag is implemented:
  166. +
  167. + * nothrottle
  168. + Forcibly overrides hotplug2 throttling mechanism. If _all_ rules that match
  169. + the given kernel event have 'nothrottle' set, hotplug2 will not wait for
  170. + children count to get under max-children limit. That allows to throttle
  171. + eg. helper application execution or modprobes, but yet keep node devices
  172. + fast.
  173. ESCAPING
  174. --------
  175. @@ -136,8 +155,9 @@
  176. SAMPLE CONFIG
  177. -------------
  178. -Below is a sample hotplug2.rules file. It loads modules to all available devices
  179. -quietly and creates device nodes for block devices.
  180. +Below is a sample hotplug2.rules file. It loads modules to all available
  181. +devices quietly and creates device nodes for block devices. Note that this
  182. +sample is not very viable for real life usage.
  183. ---------------------------------------------------------------------------------
  184. MODALIAS is set {
  185. exec modprobe -q %MODALIAS% ;
  186. @@ -146,3 +166,33 @@
  187. SUBSYSTEM == block, DEVPATH is set, MAJOR is set, MINOR is set {
  188. makedev /dev/%DEVICENAME% 0644
  189. }
  190. +
  191. +
  192. +Please find also the more complex set of rules, dedicated to handling most
  193. +common needs.
  194. +---------------------------------------------------------------------------------
  195. +#For debugging
  196. +#ACTION is set {
  197. +# printdebug
  198. +#}
  199. +
  200. +# Load modules (what old hotplug did)
  201. +MODALIAS is set {
  202. + exec modprobe -q %MODALIAS% ;
  203. +}
  204. +
  205. +# Create device nodes
  206. +DEVPATH is set, MAJOR is set, MINOR is set {
  207. + makedev /dev/%DEVICENAME% 0644
  208. +}
  209. +
  210. +# Mount a USB flashdisk
  211. +ACTION == add, PHYSDEVPATH ~~ "/usb[0-9]*/", DEVICENAME ~~ "^sd[a-z][0-9]+$", DEVPATH is set, MAJOR is set, MINOR is set {
  212. + makedev /dev/%DEVICENAME% 0644
  213. + exec mount /dev/%DEVICENAME% /mnt/%DEVICENAME%
  214. +}
  215. +
  216. +# Unmount a USB flashdisk
  217. +ACTION == remove, PHYSDEVPATH ~~ "/usb[0-9]*/", DEVICENAME ~~ "^sd[a-z][0-9]+$", MAJOR is set, MINOR is set {
  218. + exec umount /mnt/%DEVICENAME%
  219. +}
  220. diff -urN -x .svn hotplug2-0.9/docs/Makefile hotplug2/docs/Makefile
  221. --- hotplug2-0.9/docs/Makefile 2006-09-26 00:27:02.000000000 +0200
  222. +++ hotplug2/docs/Makefile 2007-06-28 14:50:59.875955008 +0200
  223. @@ -2,12 +2,13 @@
  224. BINS=
  225. SUBDIRS=
  226. -
  227. +DESTDIR=
  228. +MANDIR=/usr/share/man
  229. all:
  230. install:
  231. - $(INSTALL) $(wildcard *.8) /usr/share/man/man8/
  232. + $(INSTALL) $(wildcard *.8) $(DESTDIR)$(MANDIR)/man8/
  233. include ../common.mak
  234. diff -urN -x .svn hotplug2-0.9/examples/Makefile hotplug2/examples/Makefile
  235. --- hotplug2-0.9/examples/Makefile 2006-09-26 01:03:08.000000000 +0200
  236. +++ hotplug2/examples/Makefile 2007-06-28 14:50:59.991937376 +0200
  237. @@ -2,19 +2,23 @@
  238. BINS=
  239. SUBDIRS=
  240. +DESTDIR=
  241. +KERNELVER=`uname -r`
  242. all:
  243. install:
  244. - case "`uname -r`" in \
  245. - 2.6.*) \
  246. - $(INSTALL) hotplug2.rules-2.6kernel /etc/hotplug2.rules \
  247. - ;; \
  248. - *) \
  249. - $(INSTALL) hotplug2.rules-2.4kernel /etc/hotplug2.rules \
  250. - ;; \
  251. - esac
  252. + if ! [ -e "/etc/hotplug2.rules" ]; then \
  253. + case "$(KERNELVER)" in \
  254. + 2.6.*) \
  255. + $(INSTALL) hotplug2.rules-2.6kernel $(DESTDIR)/etc/hotplug2.rules \
  256. + ;; \
  257. + *) \
  258. + $(INSTALL) hotplug2.rules-2.4kernel $(DESTDIR)/etc/hotplug2.rules \
  259. + ;; \
  260. + esac; \
  261. + fi;
  262. include ../common.mak
  263. diff -urN -x .svn hotplug2-0.9/filemap_utils.c hotplug2/filemap_utils.c
  264. --- hotplug2-0.9/filemap_utils.c 2006-09-25 12:14:12.000000000 +0200
  265. +++ hotplug2/filemap_utils.c 2007-07-09 02:01:10.966249750 +0200
  266. @@ -16,7 +16,15 @@
  267. #include "filemap_utils.h"
  268. -int map_file(char *filename, struct filemap_t *filemap) {
  269. +/**
  270. + * Basic open/mmap wrapper to make things simpler.
  271. + *
  272. + * @1 Filename of the mmaped file
  273. + * @2 Pointer to filemap structure
  274. + *
  275. + * Returns: 0 if success, 1 otherwise
  276. + */
  277. +int map_file(const char *filename, struct filemap_t *filemap) {
  278. struct stat statbuf;
  279. filemap->fd = open(filename, O_RDONLY);
  280. @@ -40,9 +48,16 @@
  281. return 0;
  282. }
  283. +/**
  284. + * Basic close/munmap wrapper.
  285. + *
  286. + * @1 Pointer to filemap structure
  287. + *
  288. + * Returns: always 0
  289. + */
  290. int unmap_file(struct filemap_t *filemap) {
  291. - close(filemap->fd);
  292. munmap(filemap->map, filemap->size);
  293. + close(filemap->fd);
  294. return 0;
  295. }
  296. diff -urN -x .svn hotplug2-0.9/filemap_utils.h hotplug2/filemap_utils.h
  297. --- hotplug2-0.9/filemap_utils.h 2006-09-25 22:24:36.000000000 +0200
  298. +++ hotplug2/filemap_utils.h 2007-07-09 02:01:10.962249500 +0200
  299. @@ -14,6 +14,6 @@
  300. void *map;
  301. };
  302. -int map_file(char *, struct filemap_t *);
  303. +int map_file(const char *, struct filemap_t *);
  304. int unmap_file(struct filemap_t *);
  305. #endif
  306. diff -urN -x .svn hotplug2-0.9/hotplug2.c hotplug2/hotplug2.c
  307. --- hotplug2-0.9/hotplug2.c 2006-10-08 15:18:23.000000000 +0200
  308. +++ hotplug2/hotplug2.c 2007-07-09 02:01:10.962249500 +0200
  309. @@ -23,7 +23,9 @@
  310. #include <linux/netlink.h>
  311. #include "mem_utils.h"
  312. +#include "filemap_utils.h"
  313. #include "hotplug2.h"
  314. +#include "hotplug2_utils.h"
  315. #include "rules.h"
  316. #include "childlist.h"
  317. @@ -32,10 +34,16 @@
  318. child == NULL && \
  319. highest_seqnum == get_kernel_seqnum())
  320. +/*
  321. + * These variables are accessed from throughout the code.
  322. + *
  323. + * TODO: Move this into a hotplug2_t-like variable.
  324. + */
  325. event_seqnum_t highest_seqnum = 0;
  326. pid_t coldplug_p;
  327. int coldplug = 1;
  328. int persistent = 0;
  329. +int override = 0;
  330. int max_child_c = 20;
  331. int dumb = 0;
  332. int terminate = 0;
  333. @@ -45,6 +53,14 @@
  334. char *modprobe_command = NULL;
  335. +/**
  336. + * Release all memory associated with an uevent read from kernel. The given
  337. + * pointer is no longer valid, as it gets freed as well.
  338. + *
  339. + * @1 The event that is to be freed.
  340. + *
  341. + * Returns: void
  342. + */
  343. inline void free_hotplug2_event(struct hotplug2_event_t *event) {
  344. int i;
  345. @@ -57,6 +73,13 @@
  346. free(event);
  347. }
  348. +/**
  349. + * A trivial function determining the action that the uevent.
  350. + *
  351. + * @1 String containing the action name (null-terminated).
  352. + *
  353. + * Returns: Macro of the given action
  354. + */
  355. inline int get_hotplug2_event_action(char *action) {
  356. if (!strcmp(action, "add"))
  357. return ACTION_ADD;
  358. @@ -67,6 +90,14 @@
  359. return ACTION_UNKNOWN;
  360. }
  361. +/**
  362. + * Looks up a value according to the given key.
  363. + *
  364. + * @1 A hotplug event structure
  365. + * @2 Key for lookup
  366. + *
  367. + * Returns: The value of the key or NULL if no such key found
  368. + */
  369. char *get_hotplug2_value_by_key(struct hotplug2_event_t *event, char *key) {
  370. int i;
  371. @@ -78,7 +109,16 @@
  372. return NULL;
  373. }
  374. -inline int add_hotplug2_event_env(struct hotplug2_event_t *event, char *item) {
  375. +/**
  376. + * Appends a key-value pair described by the second argument to the
  377. + * hotplug event.
  378. + *
  379. + * @1 A hotplug event structure
  380. + * @1 An item in format "key=value" to be appended
  381. + *
  382. + * Returns: 0 if success, -1 if the string is malformed
  383. + */
  384. +int add_hotplug2_event_env(struct hotplug2_event_t *event, char *item) {
  385. char *ptr, *tmp;
  386. ptr = strchr(item, '=');
  387. @@ -94,6 +134,8 @@
  388. /*
  389. * Variables not generated by kernel but demanded nonetheless...
  390. + *
  391. + * TODO: Split this to a different function
  392. */
  393. if (!strcmp(item, "DEVPATH")) {
  394. event->env_vars_c++;
  395. @@ -109,6 +151,15 @@
  396. return 0;
  397. }
  398. +/**
  399. + * Duplicates all allocated memory of a source hotplug event
  400. + * and returns a new hotplug event, an identical copy of the
  401. + * source event.
  402. + *
  403. + * @1 Source hotplug event structure
  404. + *
  405. + * Returns: A copy of the source event structure
  406. + */
  407. inline struct hotplug2_event_t *dup_hotplug2_event(struct hotplug2_event_t *src) {
  408. struct hotplug2_event_t *dest;
  409. int i;
  410. @@ -129,6 +180,14 @@
  411. return dest;
  412. }
  413. +/**
  414. + * Parses a string into a hotplug event structurs.
  415. + *
  416. + * @1 The event string (not null terminated)
  417. + * @2 The size of the event string
  418. + *
  419. + * Returns: A new event structure
  420. + */
  421. inline struct hotplug2_event_t *get_hotplug2_event(char *event_str, int size) {
  422. char *ptr;
  423. struct hotplug2_event_t *event;
  424. @@ -161,59 +220,15 @@
  425. return event;
  426. }
  427. -inline event_seqnum_t get_kernel_seqnum() {
  428. - FILE *fp;
  429. -
  430. - char filename[64];
  431. - char seqnum[64];
  432. -
  433. - strcpy(filename, sysfs_seqnum_path);
  434. -
  435. - fp = fopen(filename, "r");
  436. - if (fp == NULL)
  437. - return 0;
  438. -
  439. - fread(seqnum, 1, 64, fp);
  440. - fclose(fp);
  441. -
  442. - return strtoull(seqnum, NULL, 0);
  443. -}
  444. -
  445. -inline int init_netlink_socket() {
  446. - int netlink_socket;
  447. - struct sockaddr_nl snl;
  448. - int buffersize = 16 * 1024 * 1024;
  449. -
  450. - memset(&snl, 0x00, sizeof(struct sockaddr_nl));
  451. - snl.nl_family = AF_NETLINK;
  452. - snl.nl_pid = getpid();
  453. - snl.nl_groups = 1;
  454. - netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  455. - if (netlink_socket == -1) {
  456. - ERROR("opening netlink","Failed socket: %s.", strerror(errno));
  457. - return -1;
  458. - }
  459. -
  460. - if (setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize))) {
  461. - ERROR("opening netlink","Failed setsockopt: %s. (non-critical)", strerror(errno));
  462. -
  463. - /* Somewhat safe default. */
  464. - buffersize = 106496;
  465. -
  466. - if (setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize))) {
  467. - ERROR("opening netlink","Failed setsockopt: %s. (critical)", strerror(errno));
  468. - }
  469. - }
  470. -
  471. - if (bind(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl))) {
  472. - ERROR("opening netlink","Failed bind: %s.", strerror(errno));
  473. - close(netlink_socket);
  474. - return -1;
  475. - }
  476. -
  477. - return netlink_socket;
  478. -}
  479. -
  480. +/**
  481. + * Evaluates an argument into a true/false value.
  482. + *
  483. + * @1 argument
  484. + * @2 argument flag
  485. + * @3 pointer to output value
  486. + *
  487. + * Returns: 0 if success, -1 otherwise
  488. + */
  489. int get_bool_opt(char *argv, char *name, int *value) {
  490. int rv = -1;
  491. @@ -238,7 +253,13 @@
  492. }
  493. }
  494. -void cleanup(void) {
  495. +/**
  496. + * Performs a cleanup; closes uevent socket, resets signal
  497. + * handlers, waits for all the children.
  498. + *
  499. + * Returns: void
  500. + */
  501. +void cleanup() {
  502. pid_t p;
  503. close(netlink_socket);
  504. @@ -254,6 +275,13 @@
  505. INFO("cleanup", "All children terminated.");
  506. }
  507. +/**
  508. + * Handles all signals.
  509. + *
  510. + * @1 Signal identifier
  511. + *
  512. + * Returns: void
  513. + */
  514. void sighandler(int sig) {
  515. pid_t p;
  516. @@ -313,6 +341,14 @@
  517. }
  518. #ifdef HAVE_RULES
  519. +/**
  520. + * Execute all rules for this particular event.
  521. + *
  522. + * @1 Hotplug event structure
  523. + * @2 Rules structure, containing array of rules
  524. + *
  525. + * Returns: void
  526. + */
  527. void perform_action(struct hotplug2_event_t *event, struct rules_t *rules) {
  528. int i, rv;
  529. @@ -324,13 +360,72 @@
  530. free_hotplug2_event(event);
  531. }
  532. +
  533. +/**
  534. + * Iterates through all rules, and performs an AND between all flags that
  535. + * would apply during execution (ie. all rules that have conditions matching
  536. + * the hotplug event).
  537. + *
  538. + * @1 Hotplug event structure
  539. + * @2 Rules structure, containing array of rules
  540. + *
  541. + * Returns: Flags that apply to all matching rules
  542. + */
  543. +int flags_eval(struct hotplug2_event_t *event, struct rules_t *rules) {
  544. + int flags = FLAG_ALL;
  545. + int match = 0;
  546. + int i, j;
  547. +
  548. + for (i = 0; i < rules->rules_c; i++) {
  549. + match = 1;
  550. +
  551. + for (j = 0; j < rules->rules[i].conditions_c; j++) {
  552. + if (rule_condition_eval(event, &rules->rules[i].conditions[j]) != EVAL_MATCH) {
  553. + match = 0;
  554. + break;
  555. + }
  556. + }
  557. +
  558. + /*
  559. + * Logical AND between flags we've got already and
  560. + * those we're adding.
  561. + */
  562. + if (match) {
  563. + rule_flags(&rules->rules[i]);
  564. + flags &= rules->rules[i].flags;
  565. + }
  566. + }
  567. +
  568. + /*
  569. + * A little trick; if no rule matched, we return FLAG_ALL
  570. + * and have it skipped completely.
  571. + */
  572. +
  573. + return flags;
  574. +}
  575. +#else
  576. +#define perform_action(event, rules)
  577. #endif
  578. +/**
  579. + * Blindly modprobe the modalias, nothing more.
  580. + *
  581. + * @1 Hotplug event structure
  582. + * @2 Modalias to be loaded
  583. + *
  584. + * Returns: void
  585. + */
  586. void perform_dumb_action(struct hotplug2_event_t *event, char *modalias) {
  587. free_hotplug2_event(event);
  588. execl(modprobe_command, modprobe_command, "-q", modalias, NULL);
  589. }
  590. +/**
  591. + * Attempt to figure out whether our modprobe command can handle modalias.
  592. + * If not, use our own wrapper.
  593. + *
  594. + * Returns: 0 if success, -1 otherwise
  595. + */
  596. int get_modprobe_command() {
  597. pid_t p;
  598. int fds[2];
  599. @@ -381,6 +476,9 @@
  600. }
  601. int main(int argc, char *argv[]) {
  602. + /*
  603. + * TODO, cleanup
  604. + */
  605. static char buffer[UEVENT_BUFFER_SIZE+512];
  606. struct hotplug2_event_t *tmpevent;
  607. char *modalias, *seqnum;
  608. @@ -390,28 +488,39 @@
  609. int size;
  610. int rv = 0;
  611. int i;
  612. + unsigned int flags;
  613. char *coldplug_command = NULL;
  614. + char *rules_file = HOTPLUG2_RULE_PATH;
  615. sigset_t block_mask;
  616. struct rules_t *rules = NULL;
  617. - struct stat statbuf;
  618. - void *filemap;
  619. - int rule_fd;
  620. + struct filemap_t filemap;
  621. struct options_t bool_options[] = {
  622. {"persistent", &persistent},
  623. {"coldplug", &coldplug},
  624. {"udevtrigger", &coldplug}, /* compatibility */
  625. + {"override", &override},
  626. #ifdef HAVE_RULES
  627. {"dumb", &dumb},
  628. #endif
  629. {NULL, NULL}
  630. };
  631. + /*
  632. + * We parse all the options...
  633. + */
  634. for (argc--; argc > 0; argc--) {
  635. argv++;
  636. + /*
  637. + * TODO, cleanup
  638. + */
  639. for (i = 0; bool_options[i].name != NULL; i++) {
  640. if (!get_bool_opt(*argv, bool_options[i].name, bool_options[i].value)) {
  641. + /*
  642. + * Bool options are --option or --no-options. If we handled
  643. + * it, quit iterating.
  644. + */
  645. break;
  646. } else {
  647. if (!strcmp(*argv, "--max-children")) {
  648. @@ -435,52 +544,52 @@
  649. break;
  650. modprobe_command = *argv;
  651. + } else if (!strcmp(*argv, "--set-rules-file")) {
  652. + argv++;
  653. + argc--;
  654. + if (argc <= 0)
  655. + break;
  656. +
  657. + rules_file = *argv;
  658. }
  659. }
  660. }
  661. }
  662. -#ifdef HAVE_RULES
  663. +#ifndef HAVE_RULES
  664. + /*
  665. + * We don't use rules, so we use dumb mode only.
  666. + */
  667. + dumb = 1;
  668. +#else
  669. + /*
  670. + * We're not in dumb mode, parse the rules. If we fail,
  671. + * faillback to dumb mode.
  672. + */
  673. if (!dumb) {
  674. - filemap = MAP_FAILED;
  675. - rule_fd = open(HOTPLUG2_RULE_PATH, O_RDONLY | O_NOATIME);
  676. - if (rule_fd == -1) {
  677. - dumb = 1;
  678. - ERROR("rules parse","Unable to open rules file: %s.", strerror(errno));
  679. - goto end_rules;
  680. - }
  681. -
  682. - if (fstat(rule_fd, &statbuf)) {
  683. - dumb = 1;
  684. - ERROR("rules parse","Unable to stat rules file: %s.", strerror(errno));
  685. - goto end_rules;
  686. - }
  687. -
  688. - filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, rule_fd, 0);
  689. - if (filemap == MAP_FAILED) {
  690. + if (map_file(rules_file, &filemap)) {
  691. + ERROR("rules parse","Unable to open/mmap rules file.");
  692. dumb = 1;
  693. - ERROR("rules parse","Unable to mmap rules file: %s.", strerror(errno));
  694. goto end_rules;
  695. }
  696. - rules = rules_from_config((char*)filemap);
  697. + rules = rules_from_config((char*)(filemap.map), NULL);
  698. if (rules == NULL) {
  699. ERROR("rules parse","Unable to parse rules file.");
  700. dumb = 1;
  701. }
  702. +
  703. + unmap_file(&filemap);
  704. end_rules:
  705. - if (filemap != MAP_FAILED)
  706. - munmap(filemap, statbuf.st_size);
  707. - if (rule_fd != -1)
  708. - close(rule_fd);
  709. -
  710. if (dumb == 1)
  711. ERROR("rules parse","Parsing rules failed, switching to dumb mode.");
  712. - } else if (!modprobe_command)
  713. -#else
  714. - if (dumb && !modprobe_command)
  715. + } else
  716. #endif
  717. + /*
  718. + * No modprobe command specified, let's autodetect it.
  719. + */
  720. + if (!modprobe_command)
  721. {
  722. if (get_modprobe_command()) {
  723. ERROR("modprobe_command","Unable to autodetect modprobe command.");
  724. @@ -489,7 +598,10 @@
  725. DBG("modprobe_command", "Using modprobe: `%s'.", modprobe_command);
  726. }
  727. - netlink_socket = init_netlink_socket();
  728. + /*
  729. + * Open netlink socket to read the uevents
  730. + */
  731. + netlink_socket = init_netlink_socket(NETLINK_BIND);
  732. if (netlink_socket == -1) {
  733. ERROR("netlink init","Unable to open netlink socket.");
  734. @@ -503,6 +615,9 @@
  735. signal(SIGINT, sighandler);
  736. signal(SIGCHLD, sighandler);
  737. + /*
  738. + * If we desire coldplugging, we initiate it right now.
  739. + */
  740. if (coldplug) {
  741. if (coldplug_command == NULL)
  742. coldplug_command = UDEVTRIGGER_COMMAND;
  743. @@ -523,10 +638,19 @@
  744. coldplug_p = FORK_FINISHED;
  745. }
  746. + /*
  747. + * Main loop reading uevents
  748. + */
  749. while (!terminate) {
  750. + /*
  751. + * Read the uevent packet
  752. + */
  753. size = recv(netlink_socket, &buffer, sizeof(buffer), 0);
  754. recv_errno = errno;
  755. + /*
  756. + * Parse the event into an event structure
  757. + */
  758. tmpevent = get_hotplug2_event(buffer, size);
  759. if (tmpevent == NULL) {
  760. @@ -534,26 +658,61 @@
  761. continue;
  762. }
  763. + /*
  764. + * Look up two important items of the event
  765. + */
  766. modalias = get_hotplug2_value_by_key(tmpevent, "MODALIAS");
  767. seqnum = get_hotplug2_value_by_key(tmpevent, "SEQNUM");
  768. -
  769. +
  770. + /*
  771. + * Seqnum is necessary not to end up in a race with the kernel.
  772. + */
  773. if (seqnum == NULL) {
  774. free_hotplug2_event(tmpevent);
  775. ERROR("reading events", "Malformed event read (missing SEQNUM).");
  776. continue;
  777. }
  778. + /*
  779. + * Maintain seqnum continuity
  780. + */
  781. cur_seqnum = strtoull(seqnum, NULL, 0);
  782. if (cur_seqnum > highest_seqnum)
  783. highest_seqnum = cur_seqnum;
  784. - if (tmpevent->action == ACTION_ADD && (!dumb || modalias != NULL)) {
  785. + /*
  786. + * If we are in smart mode, we'll always pass. If we're in dumb mode,
  787. + * we only pass events that have 'add' action and have modalias set.
  788. + */
  789. + if ((dumb && tmpevent->action == ACTION_ADD && modalias != NULL) || (!dumb)) {
  790. + /*
  791. + * Pre-evaluation of the flags
  792. + */
  793. + if (!dumb && override) {
  794. + flags = flags_eval(tmpevent, rules);
  795. +
  796. + DBG("flags", "flag returned: %8x", flags);
  797. +
  798. + if (flags == FLAG_ALL)
  799. + continue;
  800. + } else {
  801. + flags = FLAG_UNSET;
  802. + }
  803. +
  804. /*
  805. * We have more children than we want. Wait until SIGCHLD handler reduces
  806. * their numbers.
  807. + *
  808. + * Unless, of course, we've specified otherwise and no rules that match
  809. + * need throttling.
  810. */
  811. - while (child_c >= max_child_c) {
  812. - usleep(HOTPLUG2_THROTTLE_INTERVAL);
  813. + if (!flags & FLAG_NOTHROTTLE) {
  814. + /*
  815. + * Okay, throttle away!
  816. + */
  817. + while (child_c >= max_child_c) {
  818. + usleep(HOTPLUG2_THROTTLE_INTERVAL);
  819. + }
  820. }
  821. sigemptyset(&block_mask);
  822. @@ -562,17 +721,18 @@
  823. p = fork();
  824. switch (p) {
  825. case -1:
  826. - ERROR("event","fork failed: %s.", strerror(errno));
  827. + ERROR("event", "fork failed: %s.", strerror(errno));
  828. break;
  829. case 0:
  830. + /*
  831. + * TODO: We do not have to dup here, or do we?
  832. + */
  833. sigprocmask(SIG_UNBLOCK, &block_mask, 0);
  834. signal(SIGCHLD, SIG_DFL);
  835. signal(SIGUSR1, SIG_DFL);
  836. -#ifdef HAVE_RULES
  837. if (!dumb)
  838. perform_action(dup_hotplug2_event(tmpevent), rules);
  839. else
  840. -#endif
  841. perform_dumb_action(dup_hotplug2_event(tmpevent), modalias);
  842. exit(0);
  843. break;
  844. @@ -593,12 +753,10 @@
  845. signal(SIGINT, SIG_DFL);
  846. signal(SIGCHLD, SIG_DFL);
  847. -#ifdef HAVE_RULES
  848. if (!dumb) {
  849. rules_free(rules);
  850. free(rules);
  851. }
  852. -#endif
  853. cleanup();
  854. diff -urN -x .svn hotplug2-0.9/hotplug2-dnode.c hotplug2/hotplug2-dnode.c
  855. --- hotplug2-0.9/hotplug2-dnode.c 2006-09-26 17:35:35.000000000 +0200
  856. +++ hotplug2/hotplug2-dnode.c 2007-07-09 01:17:14.869504000 +0200
  857. @@ -27,6 +27,7 @@
  858. #include "mem_utils.h"
  859. #include "hotplug2.h"
  860. +#include "hotplug2_utils.h"
  861. #include "parser_utils.h"
  862. #define MODALIAS_MAX_LEN 1024
  863. @@ -45,59 +46,17 @@
  864. #define TEST_INPUT_BIT(i,bm) (bm[i / BITS_PER_LONG] & (((unsigned long)1) << (i%BITS_PER_LONG)))
  865. -int init_netlink_socket() {
  866. - int netlink_socket;
  867. - struct sockaddr_nl snl;
  868. - int buffersize = 16 * 1024 * 1024;
  869. -
  870. - memset(&snl, 0x00, sizeof(struct sockaddr_nl));
  871. - snl.nl_family = AF_NETLINK;
  872. - snl.nl_pid = getpid();
  873. - snl.nl_groups = 1;
  874. - netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  875. - if (netlink_socket == -1) {
  876. - ERROR("opening netlink","Failed socket: %s.", strerror(errno));
  877. - return -1;
  878. - }
  879. -
  880. - if (setsockopt(netlink_socket, SOL_SOCKET, SO_SNDBUFFORCE, &buffersize, sizeof(buffersize))) {
  881. - ERROR("opening netlink","Failed setsockopt: %s. (non-critical)", strerror(errno));
  882. -
  883. - /* Somewhat safe default. */
  884. - buffersize = 106496;
  885. -
  886. - if (setsockopt(netlink_socket, SOL_SOCKET, SO_SNDBUF, &buffersize, sizeof(buffersize))) {
  887. - ERROR("opening netlink","Failed setsockopt: %s. (critical)", strerror(errno));
  888. - }
  889. - }
  890. -
  891. - if (connect(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl))) {
  892. - ERROR("opening netlink","Failed bind: %s.", strerror(errno));
  893. - close(netlink_socket);
  894. - return -1;
  895. - }
  896. -
  897. - return netlink_socket;
  898. -}
  899. -
  900. -inline event_seqnum_t get_kernel_seqnum() {
  901. - FILE *fp;
  902. -
  903. - char filename[64];
  904. - char seqnum[64];
  905. -
  906. - strcpy(filename, sysfs_seqnum_path);
  907. -
  908. - fp = fopen(filename, "r");
  909. - if (fp == NULL)
  910. - return 0;
  911. -
  912. - fread(seqnum, 1, 64, fp);
  913. - fclose(fp);
  914. -
  915. - return strtoull(seqnum, NULL, 0);
  916. -}
  917. -
  918. +/**
  919. + * Parses a bitmap; output is a list of offsets of bits of a bitmap
  920. + * of arbitrary size that are set to 1.
  921. + *
  922. + * @1 Name of the bitmap parsed
  923. + * @2 The actual bitmap pointer
  924. + * @3 Lower boundary of the bitmap
  925. + * @4 Upper boundary of the bitmap
  926. + *
  927. + * Returns: Newly allocated string containing the offsets
  928. + */
  929. char *bitmap_to_bitstring(char name, unsigned long *bm, unsigned int min_bit, unsigned int max_bit)
  930. {
  931. char *rv;
  932. @@ -120,6 +79,15 @@
  933. return rv;
  934. }
  935. +/**
  936. + * Reverses the bitmap_to_bitstring function.
  937. + *
  938. + * @1 Bitstring to be converted
  939. + * @2 Output bitmap
  940. + * @3 Size of the whole bitmap
  941. + *
  942. + * Returns: void
  943. + */
  944. void string_to_bitmap(char *input, unsigned long *bitmap, int bm_len) {
  945. char *token, *ptr;
  946. int i = 0;
  947. @@ -146,6 +114,14 @@
  948. } \
  949. bitmap = bitmap_to_bitstring(name, bitmap ## _bits, min, mapkey ## _MAX);
  950. +/**
  951. + * Creates an input modalias out of preset environmental variables.
  952. + *
  953. + * @1 Pointer to where modalias will be created
  954. + * @2 Maximum size of the modalias
  955. + *
  956. + * Returns: 0 if success, -1 otherwise
  957. + */
  958. int get_input_modalias(char *modalias, int modalias_len) {
  959. char *product_env;
  960. char *ptr;
  961. @@ -245,6 +221,14 @@
  962. #undef NBITS
  963. #undef TEST_INPUT_BIT
  964. +/**
  965. + * Creates a PCI modalias out of preset environmental variables.
  966. + *
  967. + * @1 Pointer to where modalias will be created
  968. + * @2 Maximum size of the modalias
  969. + *
  970. + * Returns: 0 if success, -1 otherwise
  971. + */
  972. int get_pci_modalias(char *modalias, int modalias_len) {
  973. char *class_env, *id_env, *subsys_env;
  974. char *ptr;
  975. @@ -290,6 +274,15 @@
  976. return 0;
  977. }
  978. +/**
  979. + * Creates an IEEE1394 (FireWire) modalias out of preset environmental
  980. + * variables.
  981. + *
  982. + * @1 Pointer to where modalias will be created
  983. + * @2 Maximum size of the modalias
  984. + *
  985. + * Returns: 0 if success, -1 otherwise
  986. + */
  987. int get_ieee1394_modalias(char *modalias, int modalias_len) {
  988. char *vendor_env, *model_env;
  989. char *specifier_env, *version_env;
  990. @@ -317,6 +310,14 @@
  991. return 0;
  992. }
  993. +/**
  994. + * Creates a serio modalias out of preset environmental variables.
  995. + *
  996. + * @1 Pointer to where modalias will be created
  997. + * @2 Maximum size of the modalias
  998. + *
  999. + * Returns: 0 if success, -1 otherwise
  1000. + */
  1001. int get_serio_modalias(char *modalias, int modalias_len) {
  1002. char *serio_type_env, *serio_proto_env;
  1003. char *serio_id_env, *serio_extra_env;
  1004. @@ -344,6 +345,14 @@
  1005. return 0;
  1006. }
  1007. +/**
  1008. + * Creates an USB modalias out of preset environmental variables.
  1009. + *
  1010. + * @1 Pointer to where modalias will be created
  1011. + * @2 Maximum size of the modalias
  1012. + *
  1013. + * Returns: 0 if success, -1 otherwise
  1014. + */
  1015. int get_usb_modalias(char *modalias, int modalias_len) {
  1016. char *product_env, *type_env, *interface_env;
  1017. char *ptr;
  1018. @@ -409,6 +418,16 @@
  1019. return 0;
  1020. }
  1021. +/**
  1022. + * Distributes modalias generating according to the bus name.
  1023. + *
  1024. + * @1 Bus name
  1025. + * @2 Pointer to where modalias will be created
  1026. + * @3 Maximum size of the modalias
  1027. + *
  1028. + * Returns: The return value of the subsystem modalias function, or -1 if
  1029. + * no match.
  1030. + */
  1031. int get_modalias(char *bus, char *modalias, int modalias_len) {
  1032. memset(modalias, 0, modalias_len);
  1033. @@ -435,6 +454,16 @@
  1034. return -1;
  1035. }
  1036. +/**
  1037. + * Turns all environmental variables as set when invoked by /proc/sys/hotplug
  1038. + * into an uevent formatted (thus not null-terminated) string.
  1039. + *
  1040. + * @1 All environmental variables
  1041. + * @2 Bus of the event (as read from argv)
  1042. + * @3 Pointer to size of the returned uevent string
  1043. + *
  1044. + * Returns: Not null terminated uevent string.
  1045. + */
  1046. inline char *get_uevent_string(char **environ, char *bus, unsigned long *uevent_string_len) {
  1047. char *uevent_string;
  1048. char *tmp;
  1049. @@ -516,7 +545,7 @@
  1050. return 1;
  1051. }
  1052. - netlink_socket = init_netlink_socket();
  1053. + netlink_socket = init_netlink_socket(NETLINK_CONNECT);
  1054. if (netlink_socket == -1) {
  1055. ERROR("netlink init","Unable to open netlink socket.");
  1056. goto exit;
  1057. diff -urN -x .svn hotplug2-0.9/hotplug2.h hotplug2/hotplug2.h
  1058. --- hotplug2-0.9/hotplug2.h 2006-10-08 12:21:56.000000000 +0200
  1059. +++ hotplug2/hotplug2.h 2007-07-09 01:17:14.865503750 +0200
  1060. @@ -34,7 +34,7 @@
  1061. #endif
  1062. #ifndef O_NOATIME
  1063. -#define O_NOATIME 01000000
  1064. +#define O_NOATIME 01000000
  1065. #endif
  1066. #define ERROR(action, fmt, arg...) fprintf(stderr, "[%s]: " fmt"\n", action, ##arg);
  1067. @@ -47,7 +47,7 @@
  1068. #define UEVENT_BUFFER_SIZE 2048
  1069. #define HOTPLUG2_POLL_INTERVAL 20000
  1070. -#define HOTPLUG2_THROTTLE_INTERVAL 10000
  1071. +#define HOTPLUG2_THROTTLE_INTERVAL 10000
  1072. #define HOTPLUG2_RULE_PATH "/etc/hotplug2.rules"
  1073. #define ACTION_ADD 0
  1074. diff -urN -x .svn hotplug2-0.9/hotplug2_utils.c hotplug2/hotplug2_utils.c
  1075. --- hotplug2-0.9/hotplug2_utils.c 1970-01-01 01:00:00.000000000 +0100
  1076. +++ hotplug2/hotplug2_utils.c 2007-07-09 01:17:14.869504000 +0200
  1077. @@ -0,0 +1,96 @@
  1078. +#include <stdio.h>
  1079. +#include <string.h>
  1080. +#include <stdlib.h>
  1081. +#include <fcntl.h>
  1082. +#include <stdio.h>
  1083. +#include <unistd.h>
  1084. +#include <errno.h>
  1085. +#include <sys/socket.h>
  1086. +#include <sys/types.h>
  1087. +#include <sys/un.h>
  1088. +#include <sys/wait.h>
  1089. +#include <linux/types.h>
  1090. +#include <linux/netlink.h>
  1091. +
  1092. +#include "hotplug2_utils.h"
  1093. +
  1094. +/**
  1095. + * A trivial function that reads kernel seqnum from sysfs.
  1096. + *
  1097. + * Returns: Seqnum as read from sysfs
  1098. + */
  1099. +inline event_seqnum_t get_kernel_seqnum() {
  1100. + FILE *fp;
  1101. +
  1102. + char filename[64];
  1103. + char seqnum[64];
  1104. +
  1105. + strcpy(filename, sysfs_seqnum_path);
  1106. +
  1107. + fp = fopen(filename, "r");
  1108. + if (fp == NULL)
  1109. + return 0;
  1110. +
  1111. + fread(seqnum, 1, 64, fp);
  1112. + fclose(fp);
  1113. +
  1114. + return strtoull(seqnum, NULL, 0);
  1115. +}
  1116. +
  1117. +/**
  1118. + * Opens a PF_NETLINK socket into the kernel, to read uevents.
  1119. + *
  1120. + * @1 Specifies type of socket (whether we bind or whether we connect)
  1121. + *
  1122. + * Returns: Socket fd if succesful, -1 otherwise.
  1123. + */
  1124. +inline int init_netlink_socket(int type) {
  1125. + int netlink_socket;
  1126. + struct sockaddr_nl snl;
  1127. + int buffersize = 16 * 1024 * 1024;
  1128. +
  1129. + memset(&snl, 0x00, sizeof(struct sockaddr_nl));
  1130. + snl.nl_family = AF_NETLINK;
  1131. + snl.nl_pid = getpid();
  1132. + snl.nl_groups = 1;
  1133. + netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  1134. + if (netlink_socket == -1) {
  1135. + ERROR("opening netlink","Failed socket: %s.", strerror(errno));
  1136. + return -1;
  1137. + }
  1138. +
  1139. + /*
  1140. + * We're trying to override buffer size. If we fail, we attempt to set a big buffer and pray.
  1141. + */
  1142. + if (setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize))) {
  1143. + ERROR("opening netlink","Failed setsockopt: %s. (non-critical)", strerror(errno));
  1144. +
  1145. + /* Somewhat safe default. */
  1146. + buffersize = 106496;
  1147. +
  1148. + if (setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize))) {
  1149. + ERROR("opening netlink","Failed setsockopt: %s. (critical)", strerror(errno));
  1150. + }
  1151. + }
  1152. +
  1153. + /*
  1154. + * hotplug2-dnode performs connect, while hotplug2 daemon binds
  1155. + */
  1156. + switch (type) {
  1157. + case NETLINK_CONNECT:
  1158. + if (connect(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl))) {
  1159. + ERROR("opening netlink","Failed connect: %s.", strerror(errno));
  1160. + close(netlink_socket);
  1161. + return -1;
  1162. + }
  1163. +
  1164. + default:
  1165. + if (bind(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl))) {
  1166. + ERROR("opening netlink","Failed bind: %s.", strerror(errno));
  1167. + close(netlink_socket);
  1168. + return -1;
  1169. + }
  1170. + }
  1171. +
  1172. + return netlink_socket;
  1173. +}
  1174. diff -urN -x .svn hotplug2-0.9/hotplug2_utils.h hotplug2/hotplug2_utils.h
  1175. --- hotplug2-0.9/hotplug2_utils.h 1970-01-01 01:00:00.000000000 +0100
  1176. +++ hotplug2/hotplug2_utils.h 2007-07-09 01:17:14.869504000 +0200
  1177. @@ -0,0 +1,21 @@
  1178. +/*****************************************************************************\
  1179. +* _ _ _ _ ___ *
  1180. +* | || | ___ | |_ _ __ | | _ _ __ _ |_ ) *
  1181. +* | __ |/ _ \| _|| '_ \| || || |/ _` | / / *
  1182. +* |_||_|\___/ \__|| .__/|_| \_,_|\__, |/___| *
  1183. +* |_| |___/ *
  1184. +\*****************************************************************************/
  1185. +
  1186. +#ifndef HOTPLUG2_UTILS_H
  1187. +#define HOTPLUG2_UTILS_H 1
  1188. +
  1189. +#include "hotplug2.h"
  1190. +
  1191. +#define NETLINK_UNDEFINED 0
  1192. +#define NETLINK_CONNECT 1
  1193. +#define NETLINK_BIND 2
  1194. +
  1195. +inline event_seqnum_t get_kernel_seqnum();
  1196. +inline int init_netlink_socket(int);
  1197. +
  1198. +#endif
  1199. diff -urN -x .svn hotplug2-0.9/linux24_compat/hotplug2-coldplug-2.4.c hotplug2/linux24_compat/hotplug2-coldplug-2.4.c
  1200. --- hotplug2-0.9/linux24_compat/hotplug2-coldplug-2.4.c 2006-09-25 22:22:47.000000000 +0200
  1201. +++ hotplug2/linux24_compat/hotplug2-coldplug-2.4.c 2007-07-09 01:17:14.793499250 +0200
  1202. @@ -28,59 +28,7 @@
  1203. #include "../mem_utils.h"
  1204. #include "../parser_utils.h"
  1205. #include "../filemap_utils.h"
  1206. -
  1207. -inline int init_netlink_socket() {
  1208. - int netlink_socket;
  1209. - struct sockaddr_nl snl;
  1210. - int buffersize = 16 * 1024 * 1024;
  1211. -
  1212. - memset(&snl, 0x00, sizeof(struct sockaddr_nl));
  1213. - snl.nl_family = AF_NETLINK;
  1214. - snl.nl_pid = getpid();
  1215. - snl.nl_groups = 1;
  1216. - netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  1217. - if (netlink_socket == -1) {
  1218. - ERROR("opening netlink","Failed socket: %s.", strerror(errno));
  1219. - return -1;
  1220. - }
  1221. -
  1222. - if (setsockopt(netlink_socket, SOL_SOCKET, SO_SNDBUFFORCE, &buffersize, sizeof(buffersize))) {
  1223. - ERROR("opening netlink","Failed setsockopt: %s. (non-critical)", strerror(errno));
  1224. -
  1225. - /* Somewhat safe default. */
  1226. - buffersize = 106496;
  1227. -
  1228. - if (setsockopt(netlink_socket, SOL_SOCKET, SO_SNDBUF, &buffersize, sizeof(buffersize))) {
  1229. - ERROR("opening netlink","Failed setsockopt: %s. (critical)", strerror(errno));
  1230. - }
  1231. - }
  1232. -
  1233. - if (connect(netlink_socket, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl))) {
  1234. - ERROR("opening netlink","Failed bind: %s.", strerror(errno));
  1235. - close(netlink_socket);
  1236. - return -1;
  1237. - }
  1238. -
  1239. - return netlink_socket;
  1240. -}
  1241. -
  1242. -inline event_seqnum_t get_kernel_seqnum() {
  1243. - FILE *fp;
  1244. -
  1245. - char filename[64];
  1246. - char seqnum[64];
  1247. -
  1248. - strcpy(filename, sysfs_seqnum_path);
  1249. -
  1250. - fp = fopen(filename, "r");
  1251. - if (fp == NULL)
  1252. - return 0;
  1253. -
  1254. - fread(seqnum, 1, 64, fp);
  1255. - fclose(fp);
  1256. -
  1257. - return strtoull(seqnum, NULL, 0);
  1258. -}
  1259. +#include "../hotplug2_utils.h"
  1260. inline char *get_uevent_string(char **environ, unsigned long *uevent_string_len) {
  1261. char *uevent_string;
  1262. @@ -413,7 +361,7 @@
  1263. int main(int argc, char *argv[], char **environ) {
  1264. int netlink_socket;
  1265. - netlink_socket = init_netlink_socket();
  1266. + netlink_socket = init_netlink_socket(NETLINK_CONNECT);
  1267. if (netlink_socket == -1) {
  1268. ERROR("netlink init","Unable to open netlink socket.");
  1269. return 1;
  1270. diff -urN -x .svn hotplug2-0.9/linux24_compat/hotplug2-modwrap.c hotplug2/linux24_compat/hotplug2-modwrap.c
  1271. --- hotplug2-0.9/linux24_compat/hotplug2-modwrap.c 2006-09-25 22:23:07.000000000 +0200
  1272. +++ hotplug2/linux24_compat/hotplug2-modwrap.c 2007-07-09 01:17:14.789499000 +0200
  1273. @@ -30,8 +30,19 @@
  1274. #include "../parser_utils.h"
  1275. #include "../filemap_utils.h"
  1276. +#define MODULES_PATH "/lib/modules/"
  1277. +#define MODULES_ALIAS "modules.alias"
  1278. +
  1279. +/**
  1280. + * A simple fork/exec wrapper
  1281. + *
  1282. + * @1 Complete argv, including app path
  1283. + *
  1284. + * Returns: -1 if error, children return value otherwise
  1285. + */
  1286. int execute(char **argv) {
  1287. pid_t p;
  1288. + int status;
  1289. p = fork();
  1290. switch (p) {
  1291. @@ -42,10 +53,11 @@
  1292. exit(1);
  1293. break;
  1294. default:
  1295. - waitpid(p, NULL, 0);
  1296. + waitpid(p, &status, 0);
  1297. break;
  1298. }
  1299. - return 0;
  1300. +
  1301. + return WEXITSTATUS(status);
  1302. }
  1303. int main(int argc, char *argv[]) {
  1304. @@ -63,21 +75,36 @@
  1305. match_alias = strdup(argv[argc - 1]);
  1306. + /*
  1307. + * If we can't do uname, we're absolutely screwed and there's no
  1308. + * sense thinking twice about anything.
  1309. + */
  1310. if (uname(&unamebuf)) {
  1311. ERROR("uname", "Unable to perform uname: %s.", strerror(errno));
  1312. return 1;
  1313. }
  1314. - /* We use this one */
  1315. + /*
  1316. + * We allow setting the modprobe command to an arbitrary value.
  1317. + *
  1318. + * The whole trick lies in executing modprobe with exactly the
  1319. + * same argv as this app was executed, except we use a different
  1320. + * argv[0] (application path) and argv[argc-1] (we substitute
  1321. + * the given modalias by the matching module name)
  1322. + */
  1323. argv[0] = getenv("MODPROBE_COMMAND");
  1324. if (argv[0] == NULL)
  1325. argv[0] = "/sbin/modprobe";
  1326. -
  1327. - /* "/lib/modules/" + "/" + "\0" */
  1328. - filename = xmalloc(15 + strlen(unamebuf.release) + strlen("modules.alias"));
  1329. - strcpy(filename, "/lib/modules/");
  1330. +
  1331. + /*
  1332. + * Compose a path, /lib/modules/`uname -r`/modules.alias
  1333. + *
  1334. + * "/lib/modules/" + "/" + "\0"
  1335. + */
  1336. + filename = xmalloc(strlen(MODULES_PATH) + strlen(unamebuf.release) + strlen(MODULES_ALIAS));
  1337. + strcpy(filename, MODULES_PATH);
  1338. strcat(filename, unamebuf.release);
  1339. - strcat(filename, "/modules.alias");
  1340. + strcat(filename, MODULES_ALIAS);
  1341. if (map_file(filename, &aliasmap)) {
  1342. ERROR("map_file", "Unable to map file: `%s'.", filename);
  1343. @@ -86,10 +113,16 @@
  1344. return 1;
  1345. }
  1346. + /*
  1347. + * Read all the aliases, match them against given parameter.
  1348. + */
  1349. nptr = aliasmap.map;
  1350. while ((line = dup_line(nptr, &nptr)) != NULL) {
  1351. nline = line;
  1352. + /*
  1353. + * We want aliases only
  1354. + */
  1355. token = dup_token(nline, &nline, isspace);
  1356. if (!token || strcmp(token, "alias")) {
  1357. free(token);
  1358. @@ -98,12 +131,18 @@
  1359. }
  1360. free(token);
  1361. + /*
  1362. + * It's an alias, so fetch it
  1363. + */
  1364. cur_alias = dup_token(nline, &nline, isspace);
  1365. if (!cur_alias) {
  1366. free(line);
  1367. continue;
  1368. }
  1369. + /*
  1370. + * And now we get the module name
  1371. + */
  1372. module = dup_token(nline, &nline, isspace);
  1373. if (!module) {
  1374. free(line);
  1375. @@ -111,10 +150,14 @@
  1376. continue;
  1377. }
  1378. + /*
  1379. + * If we match, we do the modalias->module name
  1380. + * substitution as described above and execute.
  1381. + */
  1382. if (!fnmatch(cur_alias, match_alias, 0)) {
  1383. argv[argc - 1] = module;
  1384. if (execute(argv)) {
  1385. - ERROR("execute", "Unable to execute: `%s'.", argv[0]);
  1386. + ERROR("execute", "Error during exection of: `%s'.", argv[0]);
  1387. }
  1388. }
  1389. @@ -122,6 +165,17 @@
  1390. free(module);
  1391. free(line);
  1392. }
  1393. +
  1394. + /*
  1395. + * Perhaps we didn't match anything, so we might've been given
  1396. + * a module name instead of a modalias. Try to modprobe it
  1397. + * right away.
  1398. + */
  1399. + if (strcmp(argv[argc - 1], match_alias) == 0) {
  1400. + if (execute(argv)) {
  1401. + ERROR("execute", "Error during exection of: `%s'.", argv[0]);
  1402. + }
  1403. + }
  1404. free(filename);
  1405. free(match_alias);
  1406. diff -urN -x .svn hotplug2-0.9/linux24_compat/Makefile hotplug2/linux24_compat/Makefile
  1407. --- hotplug2-0.9/linux24_compat/Makefile 2006-09-26 00:26:46.000000000 +0200
  1408. +++ hotplug2/linux24_compat/Makefile 2007-07-09 01:17:14.793499250 +0200
  1409. @@ -2,16 +2,17 @@
  1410. BINS=generate_alias hotplug2-coldplug-2.4 hotplug2-modwrap
  1411. SUBDIRS=
  1412. +DESTDIR=
  1413. all: $(BINS)
  1414. install:
  1415. - $(INSTALL_BIN) hotplug2-coldplug-2.4 hotplug2-modwrap /sbin/
  1416. - $(INSTALL_BIN) generate_alias /usr/sbin/
  1417. + $(INSTALL_BIN) hotplug2-coldplug-2.4 hotplug2-modwrap $(DESTDIR)/sbin/
  1418. + $(INSTALL_BIN) generate_alias $(DESTDIR)/usr/sbin/
  1419. -hotplug2-coldplug-2.4: hotplug2-coldplug-2.4.o ../parser_utils.o ../filemap_utils.o ../mem_utils.o
  1420. +hotplug2-coldplug-2.4: hotplug2-coldplug-2.4.o ../parser_utils.o ../filemap_utils.o ../mem_utils.o ../hotplug2_utils.o
  1421. hotplug2-modwrap: hotplug2-modwrap.o ../parser_utils.o ../filemap_utils.o ../mem_utils.o
  1422. generate_alias: generate_alias.o ../parser_utils.o ../filemap_utils.o ../mem_utils.o
  1423. diff -urN -x .svn hotplug2-0.9/Makefile hotplug2/Makefile
  1424. --- hotplug2-0.9/Makefile 2006-09-26 01:03:08.000000000 +0200
  1425. +++ hotplug2/Makefile 2007-07-09 01:17:14.869504000 +0200
  1426. @@ -2,16 +2,17 @@
  1427. BINS=hotplug2 hotplug2-dnode
  1428. SUBDIRS=linux24_compat docs examples
  1429. +DESTDIR=
  1430. all: $(BINS)
  1431. install:
  1432. - $(INSTALL_BIN) $(BINS) /sbin/
  1433. + $(INSTALL_BIN) $(BINS) $(DESTDIR)/sbin/
  1434. -hotplug2: hotplug2.o childlist.o mem_utils.o rules.o
  1435. -hotplug2-dnode: hotplug2-dnode.o mem_utils.o parser_utils.o
  1436. +hotplug2: hotplug2.o hotplug2_utils.o childlist.o mem_utils.o rules.o filemap_utils.o
  1437. +hotplug2-dnode: hotplug2-dnode.o hotplug2_utils.o mem_utils.o parser_utils.o
  1438. include common.mak
  1439. diff -urN -x .svn hotplug2-0.9/mem_utils.c hotplug2/mem_utils.c
  1440. --- hotplug2-0.9/mem_utils.c 2006-09-25 22:21:45.000000000 +0200
  1441. +++ hotplug2/mem_utils.c 2007-07-09 01:17:14.865503750 +0200
  1442. @@ -9,6 +9,13 @@
  1443. #include <stdlib.h>
  1444. #include <stdio.h>
  1445. +/**
  1446. + * A malloc wrapper. Exits if no memory.
  1447. + *
  1448. + * @1 Ammount of memory to allocate
  1449. + *
  1450. + * Returns: Pointer to freshly allocated memory
  1451. + */
  1452. inline void *xmalloc(size_t size) {
  1453. void *ptr;
  1454. ptr = malloc(size);
  1455. @@ -19,6 +26,14 @@
  1456. return ptr;
  1457. }
  1458. +/**
  1459. + * A realloc wrapper. Exits if no memory.
  1460. + *
  1461. + * @1 Old pointer
  1462. + * @2 Ammount of memory to allocate
  1463. + *
  1464. + * Returns: Pointer to reallocated memory
  1465. + */
  1466. inline void *xrealloc(void *inptr, size_t size) {
  1467. void *ptr;
  1468. ptr = realloc(inptr, size);
  1469. diff -urN -x .svn hotplug2-0.9/parser_utils.c hotplug2/parser_utils.c
  1470. --- hotplug2-0.9/parser_utils.c 2006-09-25 22:21:13.000000000 +0200
  1471. +++ hotplug2/parser_utils.c 2007-07-09 01:17:14.865503750 +0200
  1472. @@ -12,6 +12,16 @@
  1473. #include "mem_utils.h"
  1474. #include "parser_utils.h"
  1475. +/**
  1476. + * Creates a newly allocated null-terminated string representing line
  1477. + * starting at a given pointer and ending at the closest newline. If
  1478. + * no newline present, returns NULL. TODO, use dup_token
  1479. + *
  1480. + * @1 Starting pointer
  1481. + * @2 Pointer where the end position is returned
  1482. + *
  1483. + * Returns: Newly allocated string containing the line or NULL
  1484. + */
  1485. char *dup_line(char *start, char **nptr) {
  1486. char *ptr, *rv;
  1487. @@ -29,6 +39,15 @@
  1488. return rv;
  1489. }
  1490. +/**
  1491. + * Returns a token delimited by the given function.
  1492. + *
  1493. + * @1 Starting pointer
  1494. + * @2 Pointer where the end position is returned
  1495. + * @3 Function that identifies the delimiter characters
  1496. + *
  1497. + * Returns: Newly allocated string containing the token or NULL
  1498. + */
  1499. char *dup_token(char *start, char **nptr, int (*isdelimiter)(int)) {
  1500. char *ptr, *rv;
  1501. @@ -56,6 +75,16 @@
  1502. return rv;
  1503. }
  1504. +/**
  1505. + * Returns the last token delimited by the given function.
  1506. + *
  1507. + * @1 Starting pointer of the whole string
  1508. + * @2 Starting position
  1509. + * @3 Pointer where the end position is returned
  1510. + * @4 Function that identifies the delimiter characters
  1511. + *
  1512. + * Returns: Newly allocated string containing the token or NULL
  1513. + */
  1514. char *dup_token_r(char *start, char *start_string, char **nptr, int (*isdelimiter)(int)) {
  1515. char *ptr, *rv;
  1516. diff -urN -x .svn hotplug2-0.9/rules.c hotplug2/rules.c
  1517. --- hotplug2-0.9/rules.c 2006-09-29 22:19:31.000000000 +0200
  1518. +++ hotplug2/rules.c 2007-07-09 02:01:10.962249500 +0200
  1519. @@ -22,11 +22,18 @@
  1520. #include <sys/stat.h>
  1521. #include "mem_utils.h"
  1522. +#include "filemap_utils.h"
  1523. #include "hotplug2.h"
  1524. #include "rules.h"
  1525. -#define last_rule return_rules->rules[return_rules->rules_c - 1]
  1526. +/**
  1527. + * Function supplementing 'mkdir -p'.
  1528. + *
  1529. + * @1 Path to be mkdir'd
  1530. + *
  1531. + * Returns: void
  1532. + */
  1533. static void mkdir_p(char *path) {
  1534. char *ptr;
  1535. struct stat statbuf;
  1536. @@ -59,6 +66,40 @@
  1537. free(path);
  1538. }
  1539. +/**
  1540. + * Function supplementing 'rmdir -p'.
  1541. + *
  1542. + * @1 Path to be rmdir'd
  1543. + *
  1544. + * Returns: void
  1545. + */
  1546. +static void rmdir_p(char *path) {
  1547. + char *ptr;
  1548. +
  1549. + path = strdup(path);
  1550. + ptr = path;
  1551. + while (ptr != NULL) {
  1552. + ptr = strrchr(path, '/');
  1553. + if (ptr == NULL)
  1554. + break;
  1555. +
  1556. + *ptr = '\0';
  1557. +
  1558. + if (rmdir(path))
  1559. + break;
  1560. + }
  1561. + free(path);
  1562. +}
  1563. +
  1564. +/**
  1565. + * Replaces all needles by a given value.
  1566. + *
  1567. + * @1 Haystack (which gets free'd in the function)
  1568. + * @2 Needle
  1569. + * @3 Needle replacement
  1570. + *
  1571. + * Returns: Newly allocated haysteck after replacement.
  1572. + */
  1573. static char *replace_str(char *hay, char *needle, char *replacement) {
  1574. char *ptr, *start, *bptr, *buf;
  1575. int occurences, j;
  1576. @@ -128,7 +169,15 @@
  1577. return buf;
  1578. }
  1579. -inline int isescaped(char *hay, char *ptr) {
  1580. +/**
  1581. + * Trivial utility, figuring out whether a character is escaped or not.
  1582. + *
  1583. + * @1 Haystack
  1584. + * @2 Pointer to the character in question
  1585. + *
  1586. + * Returns: 1 if escaped, 0 otherwise
  1587. + */
  1588. +static inline int isescaped(char *hay, char *ptr) {
  1589. if (ptr <= hay)
  1590. return 0;
  1591. @@ -138,6 +187,15 @@
  1592. return 1;
  1593. }
  1594. +/**
  1595. + * Performs replacement of all keys by their value based on the hotplug
  1596. + * event structure. Keys are identified as strings %KEY%.
  1597. + *
  1598. + * @1 Haystack
  1599. + * @2 Hotplug event structure
  1600. + *
  1601. + * Returns: Newly allocated haystack (old is freed)
  1602. + */
  1603. static char *replace_key_by_value(char *hay, struct hotplug2_event_t *event) {
  1604. char *sptr = hay, *ptr = hay;
  1605. char *buf, *replacement;
  1606. @@ -171,6 +229,17 @@
  1607. return hay;
  1608. }
  1609. +/**
  1610. + * Obtains all information from hotplug event structure about a device node.
  1611. + * Creates the device node at a given path (expandable by keys) and with
  1612. + * given mode.
  1613. + *
  1614. + * @1 Hotplug event structure
  1615. + * @2 Path (may contain keys)
  1616. + * @3 Mode of the file
  1617. + *
  1618. + * Returns: 0 if success, non-zero otherwise
  1619. + */
  1620. static int make_dev_from_event(struct hotplug2_event_t *event, char *path, mode_t devmode) {
  1621. char *subsystem, *major, *minor, *devpath;
  1622. int rv = 1;
  1623. @@ -196,12 +265,27 @@
  1624. path = replace_key_by_value(path, event);
  1625. mkdir_p(path);
  1626. rv = mknod(path, devmode, makedev(atoi(major), atoi(minor)));
  1627. +
  1628. + /*
  1629. + * Fixes an issue caused by devmode being modified by umask.
  1630. + */
  1631. + chmod(path, devmode);
  1632. +
  1633. free(path);
  1634. return_value:
  1635. return rv;
  1636. }
  1637. +/**
  1638. + * Execute an application without invoking a shell.
  1639. + *
  1640. + * @1 Hotplug event structure
  1641. + * @2 Path to the application, with expandable keys
  1642. + * @3 Argv for the application, with expandable keys
  1643. + *
  1644. + * Returns: Exit status of the application.
  1645. + */
  1646. static int exec_noshell(struct hotplug2_event_t *event, char *application, char **argv) {
  1647. pid_t p;
  1648. int i, status;
  1649. @@ -211,11 +295,12 @@
  1650. case -1:
  1651. return -1;
  1652. case 0:
  1653. + application = replace_key_by_value(strdup(application), event);
  1654. for (i = 0; argv[i] != NULL; i++) {
  1655. argv[i] = replace_key_by_value(argv[i], event);
  1656. }
  1657. execvp(application, argv);
  1658. - exit(0);
  1659. + exit(127);
  1660. break;
  1661. default:
  1662. if (waitpid(p, &status, 0) == -1)
  1663. @@ -226,6 +311,14 @@
  1664. }
  1665. }
  1666. +/**
  1667. + * Execute an application while invoking a shell.
  1668. + *
  1669. + * @1 Hotplug event structure
  1670. + * @2 The application and all its arguments, with expandable keys
  1671. + *
  1672. + * Returns: Exit status of the application.
  1673. + */
  1674. static int exec_shell(struct hotplug2_event_t *event, char *application) {
  1675. int rv;
  1676. @@ -235,6 +328,15 @@
  1677. return rv;
  1678. }
  1679. +/**
  1680. + * Create a symlink, with necessary parent directories.
  1681. + *
  1682. + * @1 Hotplug event structure
  1683. + * @2 Link target, with expandable keys
  1684. + * @3 Link name, with expandable keys
  1685. + *
  1686. + * Returns: return value of symlink()
  1687. + */
  1688. static int make_symlink(struct hotplug2_event_t *event, char *target, char *linkname) {
  1689. int rv;
  1690. @@ -250,11 +352,50 @@
  1691. return rv;
  1692. }
  1693. -static int chown_chgrp(int action, char *file, char *param) {
  1694. +/**
  1695. + * Chmod a given file.
  1696. + *
  1697. + * @1 Hotplug event structure
  1698. + * @2 File name, with expandable keys
  1699. + * @3 Chmod value, with expandable keys
  1700. + *
  1701. + * Returns: return value of chmod()
  1702. + */
  1703. +static int chmod_file(struct hotplug2_event_t *event, char *file, char *value) {
  1704. + int rv;
  1705. +
  1706. + file = replace_key_by_value(strdup(file), event);
  1707. + value = replace_key_by_value(strdup(value), event);
  1708. +
  1709. + rv = chmod(file, strtoul(value, 0, 8));
  1710. +
  1711. + free(file);
  1712. + free(value);
  1713. +
  1714. + return rv;
  1715. +}
  1716. +
  1717. +
  1718. +/**
  1719. + * Change owner or group of a given file.
  1720. + *
  1721. + * @1 Hotplug event structure
  1722. + * @2 Whether we chown or chgrp
  1723. + * @3 Filename, with expandable keys
  1724. + * @4 Group or user name, with expandable keys
  1725. + *
  1726. + * Returns: return value of chown()
  1727. + */
  1728. +static int chown_chgrp(struct hotplug2_event_t *event, int action, char *file, char *param) {
  1729. struct group *grp;
  1730. struct passwd *pwd;
  1731. int rv;
  1732. -
  1733. +
  1734. + file = replace_key_by_value(strdup(file), event);
  1735. + param = replace_key_by_value(strdup(param), event);
  1736. +
  1737. + rv = -1;
  1738. +
  1739. switch (action) {
  1740. case ACT_CHOWN:
  1741. pwd = getpwnam(param);
  1742. @@ -265,11 +406,37 @@
  1743. rv = chown(file, -1, grp->gr_gid);
  1744. break;
  1745. }
  1746. +
  1747. + free(file);
  1748. + free(param);
  1749. - return -1;
  1750. + return rv;
  1751. +}
  1752. +
  1753. +/**
  1754. + * Prints all uevent keys.
  1755. + *
  1756. + * @1 Hotplug event structure
  1757. + *
  1758. + * Returns: void
  1759. + */
  1760. +static void print_debug(struct hotplug2_event_t *event) {
  1761. + int i;
  1762. +
  1763. + for (i = 0; i < event->env_vars_c; i++)
  1764. + printf("%s=%s\n", event->env_vars[i].key, event->env_vars[i].value);
  1765. }
  1766. -static int rule_condition_eval(struct hotplug2_event_t *event, struct condition_t *condition) {
  1767. +/**
  1768. + * Evaluates a condition according to a given hotplug event structure.
  1769. + *
  1770. + * @1 Hotplug event structure
  1771. + * @2 Condition to be evaluated
  1772. + *
  1773. + * Returns: 1 if match, 0 if no match, EVAL_NOT_AVAILABLE if unable to
  1774. + * perform evaluation
  1775. + */
  1776. +int rule_condition_eval(struct hotplug2_event_t *event, struct condition_t *condition) {
  1777. int rv;
  1778. char *event_value = NULL;
  1779. regex_t preg;
  1780. @@ -314,6 +481,16 @@
  1781. return EVAL_NOT_AVAILABLE;
  1782. }
  1783. +/**
  1784. + * Executes a rule. Contains evaluation of all conditions prior
  1785. + * to execution.
  1786. + *
  1787. + * @1 Hotplug event structure
  1788. + * @2 The rule to be executed
  1789. + *
  1790. + * Returns: 0 if success, -1 if the whole event is to be
  1791. + * discared, 1 if bail out of this particular rule was required
  1792. + */
  1793. int rule_execute(struct hotplug2_event_t *event, struct rule_t *rule) {
  1794. int i, last_rv;
  1795. @@ -347,11 +524,11 @@
  1796. last_rv = make_dev_from_event(event, rule->actions[i].parameter[0], strtoul(rule->actions[i].parameter[1], NULL, 0));
  1797. break;
  1798. case ACT_CHMOD:
  1799. - last_rv = chmod(rule->actions[i].parameter[0], strtoul(rule->actions[i].parameter[1], NULL, 0));
  1800. + last_rv = chmod_file(event, rule->actions[i].parameter[0], rule->actions[i].parameter[1]);
  1801. break;
  1802. case ACT_CHOWN:
  1803. case ACT_CHGRP:
  1804. - last_rv = chown_chgrp(rule->actions[i].type, rule->actions[i].parameter[0], rule->actions[i].parameter[1]);
  1805. + last_rv = chown_chgrp(event, rule->actions[i].type, rule->actions[i].parameter[0], rule->actions[i].parameter[1]);
  1806. break;
  1807. case ACT_SYMLINK:
  1808. last_rv = make_symlink(event, rule->actions[i].parameter[0], rule->actions[i].parameter[1]);
  1809. @@ -365,12 +542,49 @@
  1810. case ACT_SETENV:
  1811. last_rv = setenv(rule->actions[i].parameter[0], rule->actions[i].parameter[1], 1);
  1812. break;
  1813. + case ACT_REMOVE:
  1814. + last_rv = unlink(rule->actions[i].parameter[0]);
  1815. + rmdir_p(rule->actions[i].parameter[0]);
  1816. + break;
  1817. + case ACT_DEBUG:
  1818. + print_debug(event);
  1819. + last_rv = 0;
  1820. + break;
  1821. }
  1822. }
  1823. return 0;
  1824. }
  1825. +/**
  1826. + * Sets the flags of the given rule.
  1827. + *
  1828. + * @1 Rule structure
  1829. + *
  1830. + * Returns: void
  1831. + */
  1832. +void rule_flags(struct rule_t *rule) {
  1833. + int i;
  1834. +
  1835. + for (i = 0; i < rule->actions_c; i++) {
  1836. + switch (rule->actions[i].type) {
  1837. + case ACT_FLAG_NOTHROTTLE:
  1838. + rule->flags |= FLAG_NOTHROTTLE;
  1839. + break;
  1840. + }
  1841. + }
  1842. +
  1843. + return;
  1844. +}
  1845. +
  1846. +/**
  1847. + * Checks whether the given character should initiate
  1848. + * further parsing.
  1849. + *
  1850. + * @1 Character to examine
  1851. + *
  1852. + * Returns: 1 if it should, 0 otherwise
  1853. + */
  1854. static inline int isinitiator(int c) {
  1855. switch (c) {
  1856. case ',':
  1857. @@ -383,6 +597,16 @@
  1858. return 0;
  1859. }
  1860. +/**
  1861. + * Appends a character to a buffer. Enlarges if necessary.
  1862. + *
  1863. + * @1 Pointer to the buffer
  1864. + * @2 Pointer to buffer size
  1865. + * @3 Pointer to last buffer character
  1866. + * @4 Appended character
  1867. + *
  1868. + * Returns: void
  1869. + */
  1870. static inline void add_buffer(char **buf, int *blen, int *slen, char c) {
  1871. if (*slen + 1 >= *blen) {
  1872. *blen = *blen + 64;
  1873. @@ -394,6 +618,14 @@
  1874. *slen += 1;
  1875. }
  1876. +/**
  1877. + * Parses a string into a syntactically acceptable value.
  1878. + *
  1879. + * @1 Input string
  1880. + * @2 Pointer to the new position
  1881. + *
  1882. + * Returns: Newly allocated string.
  1883. + */
  1884. static char *rules_get_value(char *input, char **nptr) {
  1885. int quotes = QUOTES_NONE;
  1886. char *ptr = input;
  1887. @@ -471,6 +703,16 @@
  1888. return buf;
  1889. }
  1890. +/**
  1891. + * Releases all memory associated with the ruleset. TODO: Make
  1892. + * the behavior same for all _free() functions, ie. either
  1893. + * release the given pointer itself or keep it, but do it
  1894. + * in all functions!
  1895. + *
  1896. + * @1 The ruleset to be freed
  1897. + *
  1898. + * Returns: void
  1899. + */
  1900. void rules_free(struct rules_t *rules) {
  1901. int i, j, k;
  1902. @@ -492,10 +734,53 @@
  1903. free(rules->rules);
  1904. }
  1905. -struct rules_t *rules_from_config(char *input) {
  1906. - int status = STATUS_KEY, terminate;
  1907. +/**
  1908. + * Includes a rule file.
  1909. + *
  1910. + * @1 Filename
  1911. + * @2 The ruleset structure
  1912. + *
  1913. + * Returns: 0 if success, -1 otherwise
  1914. + */
  1915. +int rules_include(const char *filename, struct rules_t **return_rules) {
  1916. + struct filemap_t filemap;
  1917. + struct rules_t *rules;
  1918. +
  1919. + if (map_file(filename, &filemap)) {
  1920. + ERROR("rules parse","Unable to open/mmap rules file.");
  1921. + return -1;
  1922. + }
  1923. +
  1924. + rules = rules_from_config((char*)(filemap.map), *return_rules);
  1925. + if (rules == NULL) {
  1926. + ERROR("rules parse","Unable to parse rules file.");
  1927. + return -1;
  1928. + }
  1929. +
  1930. + unmap_file(&filemap);
  1931. +
  1932. + return 0;
  1933. +}
  1934. +
  1935. +/**
  1936. + * Parses an entire file of rules.
  1937. + *
  1938. + * @1 The whole file in memory or mmap'd
  1939. + *
  1940. + * Returns: A newly allocated ruleset.
  1941. + */
  1942. +struct rules_t *rules_from_config(char *input, struct rules_t *return_rules) {
  1943. + #define last_rule return_rules->rules[return_rules->rules_c - 1]
  1944. + int nested;
  1945. + int status;
  1946. + int terminate;
  1947. char *buf;
  1948. - struct rules_t *return_rules;
  1949. +
  1950. + /*
  1951. + * TODO: cleanup
  1952. + *
  1953. + * BIIIG cleanup... Use callbacks for actions and for internal actions.
  1954. + */
  1955. int i, j;
  1956. struct key_rec_t conditions[] = { /*NOTE: We never have parameters for conditions. */
  1957. @@ -506,6 +791,7 @@
  1958. {"!~", 0, COND_NMATCH_RE},
  1959. {NULL, 0, -1}
  1960. };
  1961. +
  1962. struct key_rec_t actions[] = {
  1963. /*one line / one command*/
  1964. {"run", 1, ACT_RUN_SHELL},
  1965. @@ -518,6 +804,9 @@
  1966. {"chmod", 2, ACT_CHMOD},
  1967. {"chgrp", 2, ACT_CHGRP},
  1968. {"setenv", 2, ACT_SETENV},
  1969. + {"remove", 1, ACT_REMOVE},
  1970. + {"nothrottle", 0, ACT_FLAG_NOTHROTTLE},
  1971. + {"printdebug", 0, ACT_DEBUG},
  1972. /*symlink*/
  1973. {"symlink", 2, ACT_SYMLINK},
  1974. {"softlink", 2, ACT_SYMLINK},
  1975. @@ -527,9 +816,19 @@
  1976. {NULL, 0, -1}
  1977. };
  1978. - return_rules = xmalloc(sizeof(struct rules_t));
  1979. - return_rules->rules_c = 1;
  1980. - return_rules->rules = xmalloc(sizeof(struct rule_t) * return_rules->rules_c);
  1981. + /*
  1982. + * A little trick for inclusion.
  1983. + */
  1984. + if (return_rules == NULL) {
  1985. + return_rules = xmalloc(sizeof(struct rules_t));
  1986. + return_rules->rules_c = 1;
  1987. + return_rules->rules = xmalloc(sizeof(struct rule_t) * return_rules->rules_c);
  1988. + nested = 0;
  1989. + } else {
  1990. + nested = 1;
  1991. + }
  1992. +
  1993. + status = STATUS_KEY;
  1994. last_rule.actions = NULL;
  1995. last_rule.actions_c = 0;
  1996. @@ -549,9 +848,26 @@
  1997. /* Skip to next line */
  1998. while (*input != '\0' && *input != '\n')
  1999. input++;
  2000. +
  2001. + free(buf);
  2002. + continue;
  2003. + } else if (buf[0] == '$') {
  2004. + buf++;
  2005. +
  2006. + /*
  2007. + * Warning, hack ahead...
  2008. + */
  2009. + if (!strcmp("include", buf)) {
  2010. + buf = rules_get_value(input, &input);
  2011. + if (rules_include(buf, &return_rules)) {
  2012. + ERROR("rules_include", "Unable to include ruleset '%s'!", buf);
  2013. + }
  2014. + }
  2015. +
  2016. + free(buf);
  2017. continue;
  2018. }
  2019. -
  2020. +
  2021. switch (status) {
  2022. case STATUS_KEY:
  2023. last_rule.conditions_c++;
  2024. @@ -684,8 +1000,14 @@
  2025. return_rules->rules_c--;
  2026. return return_rules;
  2027. } else {
  2028. - rules_free(return_rules);
  2029. - free(return_rules);
  2030. + /*
  2031. + * We don't want to cleanup if we're nested.
  2032. + */
  2033. + if (!nested) {
  2034. + rules_free(return_rules);
  2035. + free(return_rules);
  2036. + }
  2037. +
  2038. return NULL;
  2039. }
  2040. }
  2041. diff -urN -x .svn hotplug2-0.9/rules.h hotplug2/rules.h
  2042. --- hotplug2-0.9/rules.h 2006-09-25 13:42:22.000000000 +0200
  2043. +++ hotplug2/rules.h 2007-07-09 02:01:10.962249500 +0200
  2044. @@ -24,9 +24,12 @@
  2045. #define ACT_CHGRP 6 /* chgrp <...> */
  2046. #define ACT_CHOWN 7 /* chown <...> */
  2047. #define ACT_SYMLINK 8 /* symlink <...> */
  2048. -#define ACT_NEXT_EVENT 9 /* next */
  2049. +#define ACT_NEXT_EVENT 9 /* next */
  2050. #define ACT_NEXT_IF_FAILED 10 /* next_if_failed */
  2051. #define ACT_SETENV 11 /* setenv <...> */
  2052. +#define ACT_REMOVE 12 /* remove <...> */
  2053. +#define ACT_DEBUG 13 /* debug */
  2054. +#define ACT_FLAG_NOTHROTTLE 14 /* sets 'nothrottle' flag */
  2055. #define EVAL_MATCH 1
  2056. #define EVAL_NOT_MATCH 0
  2057. @@ -42,6 +45,10 @@
  2058. #define STATUS_INITIATOR 3 /* ',' for next cond, '{' for block*/
  2059. #define STATUS_ACTION 4 /* viz ACT_* and '}' for end of block */
  2060. +#define FLAG_UNSET 0
  2061. +#define FLAG_ALL 0xffffffff
  2062. +#define FLAG_NOTHROTTLE 1 /* We want this rule to ignore max_children limit */
  2063. +
  2064. struct key_rec_t {
  2065. char *key;
  2066. int param;
  2067. @@ -65,6 +72,8 @@
  2068. struct action_t *actions;
  2069. int actions_c;
  2070. +
  2071. + unsigned int flags;
  2072. };
  2073. struct rules_t {
  2074. @@ -72,8 +81,10 @@
  2075. int rules_c;
  2076. };
  2077. +int rule_condition_eval(struct hotplug2_event_t *, struct condition_t *);
  2078. int rule_execute(struct hotplug2_event_t *, struct rule_t *);
  2079. +void rule_flags(struct rule_t *);
  2080. void rules_free(struct rules_t *);
  2081. -struct rules_t *rules_from_config(char *);
  2082. +struct rules_t *rules_from_config(char *, struct rules_t *);
  2083. #endif /* ifndef RULES_H*/
  2084. Binary files hotplug2-0.9/.swp and hotplug2/.swp differ
  2085. diff -urN -x .svn hotplug2-0.9/TODO hotplug2/TODO
  2086. --- hotplug2-0.9/TODO 1970-01-01 01:00:00.000000000 +0100
  2087. +++ hotplug2/TODO 2007-06-28 14:51:00.012934184 +0200
  2088. @@ -0,0 +1 @@
  2089. + - live rules update (via inotify)