cae7291

jiffies driver

Mar 6th, 2021
408
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.79 KB | None | 0 0
  1. #!/usr/bin/perl
  2. # FILE: ovcbin/ovcext.pm 755
  3. # ovcbin/ovcext.pm -- ovrcat archive extractor
  4. #
  5. # this is a self extracting archive
  6. # after the __DATA__ line, files are separated by:
  7. # % filename
  8.  
  9. # ovcext_cmd -- extract archive
  10. ovcext_cmd(@ARGV);
  11. exit(0);
  12.  
  13. sub ovcext_cmd
  14. {
  15. my(@argv) = @_;
  16. local($xfdata);
  17. local($xfdiv,$divcur,%ovcdiv_lookup);
  18.  
  19. $pgmtail = "ovcext";
  20. ovcinit();
  21. ovcopt(\@argv,qw(opt_go opt_f opt_t));
  22.  
  23. $xfdata = "ovrcat::DATA";
  24. $xfdata = \*$xfdata;
  25.  
  26. # first line is options
  27. ovceval($xfdata);
  28.  
  29. # data area is compressed
  30. ovcfifo($zipflg_all);
  31.  
  32. # process all lines
  33. ovcline($xfdata);
  34.  
  35. $code = ovcwait();
  36.  
  37. ovcclose(\$xfdata);
  38.  
  39. # close output units
  40. ovcdiv();
  41.  
  42. # decode base64 and decompress
  43. ovczipd_spl()
  44. if ($zipflg_spl);
  45. }
  46.  
  47. # ovceval -- decode options line
  48. sub ovceval
  49. {
  50. my($xfdata) = @_;
  51. my($buf,$err);
  52.  
  53. {
  54. $buf = <$xfdata>;
  55. chomp($buf);
  56.  
  57. # FORMAT:
  58. # $foo = 1;
  59. # @foo = (1,2);
  60. last unless ($buf =~ s/^%\s+([\@\$;])/$1/);
  61.  
  62. eval($buf);
  63.  
  64. # normal -- no error
  65. $err = $@;
  66. unless ($err) {
  67. undef($buf);
  68. last;
  69. }
  70.  
  71. chomp($err);
  72. $err = " (" . $err . ")"
  73. }
  74.  
  75. sysfault("ovceval: bad options line -- '%s'%s\n",$buf,$err)
  76. if (defined($buf));
  77. }
  78.  
  79. # ovcline -- normal line
  80. sub ovcline
  81. {
  82. my($xfdata) = @_;
  83. my($buf);
  84. my($tail);
  85.  
  86. while ($buf = <$xfdata>) {
  87. chomp($buf);
  88.  
  89. if ($buf =~ /^%\s+(.+)$/) {
  90. $tail = $1;
  91. ovcdiv($tail);
  92. next;
  93. }
  94.  
  95. print($xfdiv $buf,"\n")
  96. if (ref($xfdiv));
  97. }
  98.  
  99. }
  100.  
  101. # ovcdiv -- open output bucket
  102. sub ovcdiv
  103. {
  104. my($ofile) = @_;
  105. my($mode);
  106. my($xfcur);
  107. my($err,$prt);
  108.  
  109. ($ofile,$mode) = split(" ",$ofile);
  110.  
  111. $mode = oct($mode);
  112. $mode &= 0777;
  113.  
  114. {
  115. # close all streams
  116. unless (defined($ofile)) {
  117. while ((undef,$divcur) = each(%ovcdiv_lookup)) {
  118. close($divcur->{div_xfdst});
  119. }
  120. ###undef(%ovcdiv_lookup);
  121. last;
  122. }
  123.  
  124. # force all files to be relative to current directory
  125. $ofile = ovctail($ofile);
  126.  
  127. # get already open stream
  128. $divcur = $ovcdiv_lookup{$ofile};
  129. if (ref($divcur)) {
  130. $xfdiv = $divcur->{div_xfdst};
  131. last;
  132. }
  133. undef($xfdiv);
  134.  
  135. # now we're lenient
  136. if (-e $ofile) {
  137. msg("ovcdiv: file '%s' already exists -- ",$ofile);
  138.  
  139. unless ($opt_f) {
  140. msg("rerun with -f to force\n");
  141. last;
  142. }
  143.  
  144. msg("overwriting!\n");
  145. }
  146.  
  147. # allow subdirectory
  148. unless (defined($err)) {
  149. ovcmkdir($1)
  150. if ($ofile =~ m,^(.+)/[^/]+$,);
  151. }
  152.  
  153. msg("$pgmtail: %s %s",ovcnogo("extracting"),$ofile);
  154. msg(" chmod %3.3o",$mode)
  155. if ($mode);
  156. msg("\n");
  157.  
  158. last unless ($opt_go);
  159. last if (defined($err));
  160.  
  161. $xfcur = ovcopen(">$ofile");
  162.  
  163. $divcur = {};
  164. $ovcdiv_lookup{$ofile} = $divcur;
  165.  
  166. if ($mode) {
  167. chmod($mode,$xfcur);
  168. $divcur->{div_mode} = $mode;
  169. }
  170.  
  171. $divcur->{div_xfdst} = $xfcur;
  172. $xfdiv = $xfcur;
  173. }
  174. }
  175.  
  176. # FILE: ovcbin/ovctiny.pm
  177. # ovcbin/ovctiny.pm -- common routines
  178.  
  179. # ovcinit -- initialize for decompress
  180. sub ovcinit
  181. {
  182.  
  183. {
  184. last if (defined($ztmp));
  185. $ztmp = "/tmp/ovrcat_zip";
  186.  
  187. $PWD = $ENV{PWD};
  188.  
  189. $quo_2 = '"';
  190.  
  191. $ztmp_inp = $ztmp . "_0";
  192. $ztmp_out = $ztmp . "_1";
  193. $ztmp_perl = $ztmp . "_perl";
  194.  
  195. ovcunlink();
  196.  
  197. $ovcdbg = ($ENV{"ZPXHOWOVC"} != 0);
  198. }
  199. }
  200.  
  201. # ovcunlink -- remove temp files
  202. sub ovcunlink
  203. {
  204.  
  205. _ovcunlink($ztmp_inp,1);
  206. _ovcunlink($ztmp_out,1);
  207. _ovcunlink($ztmp_perl,($pgmtail ne "ovcext") || $opt_go);
  208. }
  209.  
  210. # _ovcunlink -- remove temp file
  211. sub _ovcunlink
  212. {
  213. my($file,$rmflg) = @_;
  214. my($found,$tag);
  215.  
  216. {
  217. last unless (defined($file));
  218.  
  219. $found = (-e $file);
  220.  
  221. $tag //= "notfound"
  222. unless ($found);
  223. $tag //= $rmflg ? "cleaning" : "keeping";
  224.  
  225. msg("ovcunlink: %s %s ...\n",$tag,$file)
  226. if (($found or $ovcdbg) and (! $ovcunlink_quiet));
  227.  
  228. unlink($file)
  229. if ($rmflg and $found);
  230. }
  231. }
  232.  
  233. # ovcopt -- decode options (tiny version)
  234. sub ovcopt
  235. {
  236. my($argv) = @_;
  237. my($opt);
  238.  
  239. while (1) {
  240. $opt = $argv->[0];
  241. last unless ($opt =~ s/^-/opt_/);
  242.  
  243. shift(@$argv);
  244. $$opt = 1;
  245. }
  246. }
  247.  
  248. # ovctail -- get tail of file
  249. sub ovctail
  250. {
  251. my($file,$sub) = @_;
  252. my(@file);
  253.  
  254. $file =~ s,^/,,;
  255. @file = split("/",$file);
  256.  
  257. ###$sub //= $opt_t;
  258. $sub //= 2;
  259.  
  260. @file = splice(@file,-$sub)
  261. if (@file >= $sub);
  262.  
  263. $file = join("/",@file);
  264.  
  265. $file;
  266. }
  267.  
  268. # ovcmkdir -- make directory
  269. sub ovcmkdir
  270. {
  271. my($odir) = @_;
  272. my(@lhs,@rhs);
  273.  
  274. @rhs = split("/",$odir);
  275.  
  276. foreach $rhs (@rhs) {
  277. push(@lhs,$rhs);
  278.  
  279. $odir = join("/",@lhs);
  280.  
  281. if ($opt_go) {
  282. next if (-d $odir);
  283. }
  284. else {
  285. next if ($ovcmkdir{$odir});
  286. $ovcmkdir{$odir} = 1;
  287. }
  288.  
  289. msg("$pgmtail: %s %s ...\n",ovcnogo("mkdir"),$odir);
  290.  
  291. next unless ($opt_go);
  292.  
  293. mkdir($odir) or
  294. sysfault("$pgmtail: unable to mkdir '%s' -- $!\n",$odir);
  295. }
  296. }
  297.  
  298. # ovcopen -- open file
  299. sub ovcopen
  300. {
  301. my($file,$who) = @_;
  302. my($xf);
  303.  
  304. $who //= $pgmtail;
  305. $who //= "ovcopen";
  306.  
  307. open($xf,$file) or
  308. sysfault("$who: unable to open '%s' -- $!\n",$file);
  309.  
  310. $xf;
  311. }
  312.  
  313. # ovcclose -- close file
  314. sub ovcclose
  315. {
  316. my($xfp) = @_;
  317. my($ref);
  318. my($xf);
  319.  
  320. {
  321. $ref = ref($xfp);
  322. last unless ($ref);
  323.  
  324. if ($ref eq "GLOB") {
  325. close($xfp);
  326. last;
  327. }
  328.  
  329. if ($ref eq "REF") {
  330. $xf = $$xfp;
  331. if (ref($xf) eq "GLOB") {
  332. close($xf);
  333. undef($$xfp);
  334. }
  335. }
  336. }
  337.  
  338. undef($xf);
  339.  
  340. $xf;
  341. }
  342.  
  343. # ovrnogo -- output message
  344. sub ovcnogo
  345. {
  346. my($str) = @_;
  347.  
  348. unless ($opt_go) {
  349. $str = "NOGO-$str";
  350. $nogo_msg = 1;
  351. }
  352.  
  353. $str;
  354. }
  355.  
  356. # ovcdbg -- debug message
  357. sub ovcdbg
  358. {
  359.  
  360. if ($ovcdbg) {
  361. printf(STDERR "[%d] ",$$);
  362. printf(STDERR @_);
  363. }
  364. }
  365.  
  366. # msg -- output message
  367. sub msg
  368. {
  369.  
  370. printf(STDERR @_);
  371. }
  372.  
  373. # msgv -- output message
  374. sub msgv
  375. {
  376.  
  377. $_ = join(" ",@_);
  378. print(STDERR $_,"\n");
  379. }
  380.  
  381. # sysfault -- output message and terminate
  382. sub sysfault
  383. {
  384.  
  385. printf(STDERR @_);
  386. exit(1);
  387. }
  388.  
  389. # ovcfifo -- dummy version
  390. sub ovcfifo
  391. {
  392. }
  393.  
  394. # ovcwait -- wait for fifo to complete
  395. sub ovcwait
  396. {
  397. my($code);
  398.  
  399. if ($pid_fifo) {
  400. waitpid($pid_fifo,0);
  401. $code = $? >> 8;
  402. }
  403.  
  404. $code;
  405. }
  406.  
  407. # prtstr -- print undefined value without defining it
  408. sub prtstr
  409. {
  410. my($val,$fmtpos,$fmtneg) = @_;
  411.  
  412. {
  413. # print undefined value as undef (without quotes)
  414. unless (defined($val)) {
  415. $val = "undef";
  416. last;
  417. }
  418.  
  419. # print references within parentheses
  420. if (ref($val)) {
  421. $val = sprintf("(%s)",$val);
  422. last;
  423. }
  424.  
  425. # get default format (string)
  426. $fmtpos //= "'%s'";
  427.  
  428. # allow error codes to come out in a different format
  429. if (defined($fmtneg) && ($val <= 0)) {
  430. $val = sprintf($fmtneg,$val);
  431. last;
  432. }
  433.  
  434. # print value using a specific format
  435. $val = sprintf($fmtpos,$val);
  436. }
  437.  
  438. $val;
  439. }
  440.  
  441. # prtnum -- print base 10 number
  442. sub prtnum
  443. {
  444. my($val) = @_;
  445.  
  446. $val = prtstr($val,"%d");
  447.  
  448. $val;
  449. }
  450.  
  451. END {
  452. msg("$pgmtail: rerun with -go to actually do it\n")
  453. if ($nogo_msg);
  454. ovcunlink();
  455. }
  456.  
  457. 1;
  458. package ovrcat;
  459. __DATA__
  460. % ;
  461. % jiffdvr/jiffies.c
  462. // NOTES:
  463. // (1) buf is a userspace/logical pointer -- it can't be accessed directly --
  464. // we must use copy_to_user
  465. // (2) static variables should be avoided -- we need to allocate a driver
  466. // private data structure -- so, we need to add .open and .release
  467. // file operations
  468. // (3) we must limit our transfer length to the len argument
  469. // (4) we must honor/update the passed in file offset (loff_t)
  470.  
  471. #include <linux/init.h>
  472. #include <linux/module.h>
  473. // does not compile too well ...
  474. #if 0
  475. #include <asm/uaccess.h>
  476. #else
  477. #include <linux/uaccess.h>
  478. #endif
  479. #include <linux/fs.h>
  480. #include <linux/sched.h>
  481. #include <linux/device.h>
  482. #include <linux/proc_fs.h>
  483. #include <linux/string.h>
  484. #include <linux/timer.h>
  485.  
  486. #include <linux/slab.h>
  487.  
  488. #define PROC_NAME "jiffies"
  489. MODULE_LICENSE("GPL 2");
  490. static int myInit(void);
  491. static void myExit(void);
  492. struct proc_dir_entry *my_proc;
  493.  
  494. // driver private data
  495. struct jiffdata {
  496. size_t len;
  497. char buf[100];
  498. };
  499.  
  500. #ifdef JIFFDEBUG
  501. #define dbgprt(_fmt...) \
  502. printk(_fmt)
  503. #else
  504. #define dbgprt(_fmt...) \
  505. do { } while (0)
  506. #endif
  507.  
  508. static int
  509. jiff_open(struct inode *ino,struct file *filp)
  510. {
  511. struct jiffdata *data;
  512.  
  513. // allocate driver private data
  514. data = kmalloc(GFP_KERNEL,sizeof(struct jiffdata));
  515. if (data == NULL)
  516. return -ENOMEM;
  517.  
  518. filp->private_data = data;
  519.  
  520. return 0;
  521. }
  522.  
  523. static int
  524. jiff_release(struct inode *ino,struct file *filp)
  525. {
  526. struct jiffdata *data = filp->private_data;
  527.  
  528. // release driver private data
  529. if (data != NULL)
  530. kfree(data->buf);
  531.  
  532. return 0;
  533. }
  534.  
  535. /* Read operation on proc */
  536. static ssize_t
  537. read_data(struct file *filp, char *buf, size_t len, loff_t *off)
  538. {
  539. struct jiffdata *data = filp->private_data;
  540. loff_t xoff = *off;
  541. ssize_t retlen;
  542. int err;
  543.  
  544. dbgprt("read_data: ENTER buf=%p len=%lu off=%p xoff=%lld f_pos=%lld\n",
  545. buf,len,off,xoff,filp->f_pos);
  546.  
  547. /* find out current value of jiffies */
  548. if (xoff == 0) {
  549. data->len = sprintf(data->buf, "Value of jiffies %lu", jiffies);
  550. dbgprt("read_data: INIT len=%lu buf='%s'\n",data->len,data->buf);
  551. data->buf[data->len++] = '\n';
  552. }
  553.  
  554. // get amount remaining to read
  555. retlen = data->len - xoff;
  556. if (retlen <= 0) {
  557. dbgprt("read_data: NORESID retlen=%ld\n",retlen);
  558. return 0;
  559. }
  560.  
  561. // limit transfer size to buffer maximum
  562. if (retlen > len)
  563. retlen = len;
  564.  
  565. do {
  566. // nothing to do
  567. if (retlen <= 0)
  568. break;
  569.  
  570. // copy data to userspace
  571. err = copy_to_user(buf,&data->buf[xoff],retlen);
  572.  
  573. // handle error on transfer
  574. if (err) {
  575. retlen = err;
  576. break;
  577. }
  578.  
  579. // advance the file position
  580. xoff += retlen;
  581. *off = xoff;
  582. } while (0);
  583.  
  584. dbgprt("read_data: EXIT retlen=%ld xoff=%lld\n",retlen,xoff);
  585.  
  586. return retlen;
  587. }
  588.  
  589. /* File operation on proc */
  590. static struct file_operations fops = {
  591. .owner = THIS_MODULE,
  592. #if 1
  593. .open = jiff_open,
  594. .release = jiff_release,
  595. #endif
  596. .read = read_data,
  597. };
  598.  
  599. /* Init of kernel module */
  600. static int __init
  601. myInit(void)
  602. {
  603. /* Create proc file with name of jiffies */
  604. my_proc = proc_create(PROC_NAME, 0666, NULL, &fops);
  605. if (my_proc == NULL) {
  606. printk(KERN_INFO "Error to create proc File\n");
  607. return -1;
  608. }
  609. return 0;
  610. }
  611.  
  612. /* exit of kernel module */
  613. static void
  614. myExit(void)
  615. {
  616. remove_proc_entry(PROC_NAME, NULL);
  617. return;
  618. }
  619.  
  620. module_init(myInit);
  621. module_exit(myExit);
  622. % jiffdvr/test.c
  623. // test -- test program for jiffies driver
  624.  
  625. #include <stdio.h>
  626. #include <stdlib.h>
  627. #include <unistd.h>
  628. #include <fcntl.h>
  629. #include <string.h>
  630. #include <errno.h>
  631.  
  632. #define sysfault(_fmt...) \
  633. do { \
  634. printf(_fmt); \
  635. exit(1); \
  636. } while (0)
  637.  
  638. void
  639. getjiff(int fd)
  640. {
  641. char buf[1];
  642. int totlen = 0;
  643.  
  644. lseek(fd,0,0);
  645.  
  646. while (totlen < 50) {
  647. int curlen = read(fd,buf,sizeof(buf));
  648.  
  649. if (curlen == 0)
  650. break;
  651.  
  652. if (curlen < 0) {
  653. sysfault("getjiff: read error -- %s\n",strerror(errno));
  654. break;
  655. }
  656.  
  657. for (int idx = 0; idx < curlen; ++idx) {
  658. #if 1
  659. fputc(buf[idx],stdout);
  660. #else
  661. printf("idx=%d '%c'\n",idx,buf[idx]);
  662. #endif
  663. }
  664.  
  665. totlen += curlen;
  666. }
  667. }
  668.  
  669. int
  670. main(void)
  671. {
  672.  
  673. int fd = open("/proc/jiffies",O_RDONLY);
  674. if (fd < 0)
  675. sysfault("main: unable to open -- %s\n",strerror(errno));
  676.  
  677. for (int iter = 1; iter <= 5; ++iter) {
  678. getjiff(fd);
  679. usleep(10000);
  680. }
  681.  
  682. close(fd);
  683.  
  684. return 0;
  685. }
  686. % jiffdvr/Makefile
  687. # Makefile -- makefile for jiffies driver
  688.  
  689. MNAME = jiffies
  690.  
  691. obj-m += $(MNAME).o
  692.  
  693. TEST = test
  694.  
  695. all: build $(TEST)
  696.  
  697. # build the driver
  698. build:
  699. make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  700.  
  701. clean:
  702. rm -f $(TEST)
  703. make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  704.  
  705. # load the driver
  706. load:
  707. shazam insmod $(MNAME).ko
  708.  
  709. # unload the driver
  710. unload:
  711. -shazam rmmod $(MNAME)
  712.  
  713. # reload the driver
  714. reload: unload load
  715.  
  716. # create userspace test program
  717. $(TEST): $(TEST).c
  718. cc -o $(TEST) -DTEST $(TEST).c
  719.  
  720. # run user test program
  721. run:
  722. ./$(TEST)
  723.  
Add Comment
Please, Sign In to add comment