diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/ChangeLog b/trunk/novell4gentoo/net-fs/novell-novfs/ChangeLog index d514663..b02d935 100644 --- a/trunk/novell4gentoo/net-fs/novell-novfs/ChangeLog +++ b/trunk/novell4gentoo/net-fs/novell-novfs/ChangeLog @@ -1,7 +1,16 @@ # ChangeLog for net-fs/novell-novfs -# Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2 +# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPL v2 # $Header: $ + 26 Jan 2007; Mario Fetka + +files/novell-novfs-1.2.0_to_2.0.0.patch, + +novell-novfs-2.0.0_p2.ebuild, +files/novell-novfs-2.0.0-config_h.patch, + +files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch, + +files/novell-novfs-2.0.0-generic_file_read.patch, + +files/novell-novfs-2.0.0-i_blksize.patch, + +files/novell-novfs-2.0.0-u.generic_ip.patch: + Update to novfs 2.0.0 + 18 Oct 2006; Mario Fetka -novell-novfs-1.2.0_p17-r1.ebuild, +novell-novfs-1.2.0_p17-r2.ebuild, -files/novell-novfs-1.2.0-2.6.17.patch, diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/Manifest b/trunk/novell4gentoo/net-fs/novell-novfs/Manifest index 67534a1..edf81bd 100644 --- a/trunk/novell4gentoo/net-fs/novell-novfs/Manifest +++ b/trunk/novell4gentoo/net-fs/novell-novfs/Manifest @@ -18,15 +18,43 @@ AUX novell-novfs-1.2.0-license.patch 18620 RMD160 0685ae1d2fe1b88872f83aac50dd54 MD5 9e1367517129a2381c4b29ba27f32052 files/novell-novfs-1.2.0-license.patch 18620 RMD160 0685ae1d2fe1b88872f83aac50dd545a90ec0bc3 files/novell-novfs-1.2.0-license.patch 18620 SHA256 e6e2c5c13b3f4fb6225532d53c1de264d6d3994fe86277b6ab15b4910c140c35 files/novell-novfs-1.2.0-license.patch 18620 +AUX novell-novfs-1.2.0_to_2.0.0.patch 934748 RMD160 83cf2e11354171acc045b3571e08654e082833fc SHA1 f6982ddf4f018baaeafbc5f19457b5ed52817643 SHA256 5a53ea406ac75848301a2d4d2e6f64a2610e1be5901de7638cdac18fb1db4667 +MD5 e835b754e6295e6c912284f19a53fa1e files/novell-novfs-1.2.0_to_2.0.0.patch 934748 +RMD160 83cf2e11354171acc045b3571e08654e082833fc files/novell-novfs-1.2.0_to_2.0.0.patch 934748 +SHA256 5a53ea406ac75848301a2d4d2e6f64a2610e1be5901de7638cdac18fb1db4667 files/novell-novfs-1.2.0_to_2.0.0.patch 934748 +AUX novell-novfs-2.0.0-config_h.patch 387 RMD160 c029426c8cfe7d6f8c63aefa3f94c801c8f397d8 SHA1 b43868344bc1d0d93ed12b325278a85fe49da767 SHA256 6ef79f82f4fbc2e15e0e914767166a9e7424426bc6a2a8a6597f6cc33738e17c +MD5 ce1ba8bd6c62ed620571dfd89e97eb9c files/novell-novfs-2.0.0-config_h.patch 387 +RMD160 c029426c8cfe7d6f8c63aefa3f94c801c8f397d8 files/novell-novfs-2.0.0-config_h.patch 387 +SHA256 6ef79f82f4fbc2e15e0e914767166a9e7424426bc6a2a8a6597f6cc33738e17c files/novell-novfs-2.0.0-config_h.patch 387 +AUX novell-novfs-2.0.0-dont_use_tasklist_lock.patch 697 RMD160 a431437c46ba7ae8dd2105f785533d07c632e353 SHA1 c35467e9646d196e6a13f8edf19a266a9f42c512 SHA256 57e09616338ef0d6c8084b31eb5faf4acdcf8a2789a95462dde11e4bc7832818 +MD5 d37acca52d7eed5a32fc59ce0c03027f files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch 697 +RMD160 a431437c46ba7ae8dd2105f785533d07c632e353 files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch 697 +SHA256 57e09616338ef0d6c8084b31eb5faf4acdcf8a2789a95462dde11e4bc7832818 files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch 697 +AUX novell-novfs-2.0.0-generic_file_read.patch 749 RMD160 5e57f0392dfa973fc94100c032463292347b883c SHA1 b2f985d366c1031fbc3d664d8933fabb61e2fe0a SHA256 9783dc6082597175af79073ec32e550210907cc7b0f1130d43cf65c9fed6d419 +MD5 ad0967dafd28c60736f5bacd80431300 files/novell-novfs-2.0.0-generic_file_read.patch 749 +RMD160 5e57f0392dfa973fc94100c032463292347b883c files/novell-novfs-2.0.0-generic_file_read.patch 749 +SHA256 9783dc6082597175af79073ec32e550210907cc7b0f1130d43cf65c9fed6d419 files/novell-novfs-2.0.0-generic_file_read.patch 749 +AUX novell-novfs-2.0.0-i_blksize.patch 2920 RMD160 8ae931e01954ee69288ece87bf67bafb81172ae3 SHA1 728aa3f689fbfe64966b78d54e85a2dd9df0ba58 SHA256 5fa30bf88f252e07481f03b2e875cfaff639d017f8f20c356930e973bf6e3740 +MD5 763e227d6b1ba5218633a2bc5d08402b files/novell-novfs-2.0.0-i_blksize.patch 2920 +RMD160 8ae931e01954ee69288ece87bf67bafb81172ae3 files/novell-novfs-2.0.0-i_blksize.patch 2920 +SHA256 5fa30bf88f252e07481f03b2e875cfaff639d017f8f20c356930e973bf6e3740 files/novell-novfs-2.0.0-i_blksize.patch 2920 +AUX novell-novfs-2.0.0-u.generic_ip.patch 24168 RMD160 37046de7e80c853327f2865f45f05458970feea9 SHA1 01b9aada0bdcd411e9b152c65b6fcdc591b3dd9b SHA256 950b959d82a21902ac0579bbb8721fc22a0813bd4ed5e0bf1ee835b1ad8dfbca +MD5 95fe1b20b61bda4152c6140ef7b07241 files/novell-novfs-2.0.0-u.generic_ip.patch 24168 +RMD160 37046de7e80c853327f2865f45f05458970feea9 files/novell-novfs-2.0.0-u.generic_ip.patch 24168 +SHA256 950b959d82a21902ac0579bbb8721fc22a0813bd4ed5e0bf1ee835b1ad8dfbca files/novell-novfs-2.0.0-u.generic_ip.patch 24168 DIST novell-client-1.2-SLE10.tar.gz 13963983 RMD160 98a0aa1ecd9c4f36c158fa2cce77f51927d2f693 SHA1 14278f74c8226afabc0c602bdc31d4e20acff6b9 SHA256 ddf55b7a757a4f4e104c4aefb04639f4022d43c31171d0a914d1b765d6e78241 EBUILD novell-novfs-1.2.0_p17-r2.ebuild 1489 RMD160 ceb5173d5207ef5de76a81299baaaf16c3db9ce4 SHA1 2d7a71e11c7fd9477e3546e2c0383a46e4fcdb08 SHA256 662bf378500afaa0d561f6779ef9a67c7d68a4b8215bef128b402dd976478592 MD5 656ac481e9df037933ac960dbff7055e novell-novfs-1.2.0_p17-r2.ebuild 1489 RMD160 ceb5173d5207ef5de76a81299baaaf16c3db9ce4 novell-novfs-1.2.0_p17-r2.ebuild 1489 SHA256 662bf378500afaa0d561f6779ef9a67c7d68a4b8215bef128b402dd976478592 novell-novfs-1.2.0_p17-r2.ebuild 1489 -MISC ChangeLog 999 RMD160 4f77e534464f968a067785085aa17753f6a3fe7d SHA1 2b49e4067542fcffe97f3955b16573fb1fa130ce SHA256 c7a9bc989c2665e5700c4112d4cc7f0e40d9464c28ee43f9f844bed0b291130d -MD5 a7b5d13e1012cc93be895e2c8d459532 ChangeLog 999 -RMD160 4f77e534464f968a067785085aa17753f6a3fe7d ChangeLog 999 -SHA256 c7a9bc989c2665e5700c4112d4cc7f0e40d9464c28ee43f9f844bed0b291130d ChangeLog 999 +EBUILD novell-novfs-2.0.0_p2.ebuild 1555 RMD160 22b10dc232d47fb23783ac59fd39576f5e06b63b SHA1 a61b70010717297cd8e5ea15906cad4ad85edb7b SHA256 46721a52d5d4ad0b8a0bb048aee3e2f5689730209a4aa2f229507ea3be45ee1c +MD5 c26f538973a4b4dc22a95fb3b0a0b716 novell-novfs-2.0.0_p2.ebuild 1555 +RMD160 22b10dc232d47fb23783ac59fd39576f5e06b63b novell-novfs-2.0.0_p2.ebuild 1555 +SHA256 46721a52d5d4ad0b8a0bb048aee3e2f5689730209a4aa2f229507ea3be45ee1c novell-novfs-2.0.0_p2.ebuild 1555 +MISC ChangeLog 1342 RMD160 23786f799a6d783fc533b8c9542b541d787f7aab SHA1 e64ca10d54f8cb5f91ef7861431c9b9a1bba0378 SHA256 3ed62003b6977d444e0d98f194575432423402e88f18437064b053b7280a8855 +MD5 d668e2d81331acb7233358f640394cc1 ChangeLog 1342 +RMD160 23786f799a6d783fc533b8c9542b541d787f7aab ChangeLog 1342 +SHA256 3ed62003b6977d444e0d98f194575432423402e88f18437064b053b7280a8855 ChangeLog 1342 MISC metadata.xml 170 RMD160 645927a396fdc21cdeb089fe42c5397332420ea6 SHA1 ac7f48a14fec325926f9ce1be8fbf1f311b4f2e4 SHA256 d797a2ec6f9dc516c9f9c1a758ee87ad3e8c43101b5dc76c2f872d5bd4639b42 MD5 1e678929a9fec6632e227bdf2262e9a1 metadata.xml 170 RMD160 645927a396fdc21cdeb089fe42c5397332420ea6 metadata.xml 170 @@ -34,3 +62,6 @@ SHA256 d797a2ec6f9dc516c9f9c1a758ee87ad3e8c43101b5dc76c2f872d5bd4639b42 metadata MD5 dcdc80c8269e53d3a5ecd72aa4034a06 files/digest-novell-novfs-1.2.0_p17-r2 277 RMD160 4767389e6f47ba8fb5b8907a954b9f80ce106b78 files/digest-novell-novfs-1.2.0_p17-r2 277 SHA256 aa21d5b182ad571f4bedf0694cc608f211146d09e0af2bdd1addd6415a2bf0b8 files/digest-novell-novfs-1.2.0_p17-r2 277 +MD5 dcdc80c8269e53d3a5ecd72aa4034a06 files/digest-novell-novfs-2.0.0_p2 277 +RMD160 4767389e6f47ba8fb5b8907a954b9f80ce106b78 files/digest-novell-novfs-2.0.0_p2 277 +SHA256 aa21d5b182ad571f4bedf0694cc608f211146d09e0af2bdd1addd6415a2bf0b8 files/digest-novell-novfs-2.0.0_p2 277 diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/digest-novell-novfs-2.0.0_p2 b/trunk/novell4gentoo/net-fs/novell-novfs/files/digest-novell-novfs-2.0.0_p2 new file mode 100644 index 0000000..9702858 --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/digest-novell-novfs-2.0.0_p2 @@ -0,0 +1,3 @@ +MD5 2aab6c7358a733d1d8d9a4e893500a36 novell-client-1.2-SLE10.tar.gz 13963983 +RMD160 98a0aa1ecd9c4f36c158fa2cce77f51927d2f693 novell-client-1.2-SLE10.tar.gz 13963983 +SHA256 ddf55b7a757a4f4e104c4aefb04639f4022d43c31171d0a914d1b765d6e78241 novell-client-1.2-SLE10.tar.gz 13963983 diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-1.2.0_to_2.0.0.patch b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-1.2.0_to_2.0.0.patch new file mode 100644 index 0000000..4321b41 --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-1.2.0_to_2.0.0.patch @@ -0,0 +1,32748 @@ +diff -uNr src.old/LICENSE src/LICENSE +--- src.old/LICENSE 1970-01-01 01:00:00.000000000 +0100 ++++ src/LICENSE 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,343 @@ ++"Use of the novfs source code is governed by the terms of the GPL:" ++ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. ++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Library General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++source code as you receive it, in any medium, provided that you ++conspicuously and appropriately publish on each copy an appropriate ++copyright notice and disclaimer of warranty; keep intact all the ++notices that refer to this License and to the absence of any warranty; ++and give any other recipients of the Program a copy of this License ++along with the Program. ++ ++You may charge a fee for the physical act of transferring a copy, and ++you may at your option offer warranty protection in exchange for a fee. ++ ++ 2. You may modify your copy or copies of the Program or any portion ++of it, thus forming a work based on the Program, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Program, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) Accompany it with the complete corresponding machine-readable ++ source code, which must be distributed under the terms of Sections ++ 1 and 2 above on a medium customarily used for software interchange; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, complete source ++code means all the source code for all modules it contains, plus any ++associated interface definition files, plus the scripts used to ++control compilation and installation of the executable. However, as a ++special exception, the source code distributed need not include ++anything that is normally distributed (in either source or binary ++form) with the major components (compiler, kernel, and so on) of the ++operating system on which the executable runs, unless that component ++itself accompanies the executable. ++ ++If distribution of executable or object code is made by offering ++access to copy from a designated place, then offering equivalent ++access to copy the source code from the same place counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program is ++void, and will automatically terminate your rights under this License. ++However, parties who have received copies, or rights, from you under ++this License will not have their licenses terminated so long as such ++parties remain in full compliance. ++ ++ 5. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program subject to ++these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 7. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Program. ++ ++If any portion of this section is held invalid or unenforceable under ++any particular circumstance, the balance of the section is intended to ++apply and the section as a whole is intended to apply in other ++circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system, which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program under this License ++may add an explicit geographical distribution limitation excluding ++those countries, so that distribution is permitted only in or among ++countries not thus excluded. In such case, this License incorporates ++the limitation as if written in the body of this License. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Program ++specifies a version number of this License which applies to it and "any ++later version", you have the option of following the terms and conditions ++either of that version or of any later version published by the Free ++Software Foundation. If the Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, write to the author ++to ask for permission. For software which is copyrighted by the Free ++Software Foundation, write to the Free Software Foundation; we sometimes ++make exceptions for this. Our decision will be guided by the two goals ++of preserving the free status of all derivatives of our free software and ++of promoting the sharing and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) year name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ , 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Library General ++Public License instead of this License. ++ +diff -uNr src.old/include/commands.h src/include/commands.h +--- src.old/include/commands.h 2006-07-11 21:24:18.000000000 +0200 ++++ src/include/commands.h 2006-10-16 15:08:23.000000000 +0200 +@@ -73,6 +73,7 @@ + #define VFS_COMMAND_SET_MOUNT_PATH 31 + #define VFS_COMMAND_GET_USER_SPACE 32 + #define VFS_COMMAND_DBG 33 ++#define VFS_COMMAND_GET_CACHE_FLAG 34 + + + #define NWD_ACCESS_QUERY 0x00000001 +@@ -1167,6 +1168,21 @@ + + } NwdCVerifyKey, *PNwdCVerifyKey; + ++typedef struct _GET_CACHE_FLAG ++{ ++ COMMAND_REQUEST_HEADER Command; ++ int pathLen; ++ unsigned char path[0]; ++ ++} GET_CACHE_FLAG_REQUEST, *PGET_CACHE_FLAG_REQUEST; ++ ++typedef struct _GET_CACHE_FLAG_REPLY ++{ ++ COMMAND_REPLY_HEADER Reply; ++ int CacheFlag; ++ ++} GET_CACHE_FLAG_REPLY, *PGET_CACHE_FLAG_REPLY; ++ + + #pragma pack(pop) + +diff -uNr src.old/novfs/Makefile src/novfs/Makefile +--- src.old/novfs/Makefile 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +@@ -1,52 +0,0 @@ +-##*++====================================================================== +-## Program Name: Novell NCP Redirector for Linux +-## File Name: Makefile +-## Version: v1.01 +-## Author: James Turner +-## +-## Abstract: This is used to generate the novfs module +-## Notes: +-## Revision History: +-## 6/10/2005 - Added lines for SuSE +-## +-## Copyright (C) 2005 Novell, Inc. +-## +-## This program is free software; you can redistribute it and/or +-## modify it under the terms of the GNU General Public License +-## as published by the Free Software Foundation; either version 2 +-## of the License, or (at your option) any later version. +-## +-## This program is distributed in the hope that it will be useful, +-## but WITHOUT ANY WARRANTY; without even the implied warranty of +-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-## GNU General Public License for more details. +-## +-## You should have received a copy of the GNU General Public License +-## along with this program; if not, write to the Free Software +-## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +-##=====================================================================--*/ +- +-# +-# Makefile for the Novell NetWare Client for Linux filesystem. +-# +-NOVFS_VFS_MAJOR = 1 +-NOVFS_VFS_MINOR = 2 +-NOVFS_VFS_SUB = 0 +-NOVFS_VFS_RELEASE = 17 +- +-# Remove # from the following line for debug version +-EXTRA_CFLAGS += -finstrument-functions +-EXTRA_CFLAGS += -g +-EXTRA_CFLAGS += -I. +-EXTRA_CFLAGS += -I$(obj)/../include +-#EXTRA_CFLAGS += -I$(obj)/../../include +-EXTRA_CFLAGS += -DNOVFS_VFS_MAJOR=$(NOVFS_VFS_MAJOR) +-EXTRA_CFLAGS += -DNOVFS_VFS_MINOR=$(NOVFS_VFS_MINOR) +-EXTRA_CFLAGS += -DNOVFS_VFS_SUB=$(NOVFS_VFS_SUB) +-EXTRA_CFLAGS += -DNOVFS_VFS_PATCH=$(NOVFS_VFS_PATCH) +-EXTRA_CFLAGS += -DNOVFS_VFS_RELEASE=$(NOVFS_VFS_RELEASE) +- +- +-obj-m := novfs.o +- +-novfs-y := inode.o proc.o profile.o daemon.o file.o scope.o nwcapi.o +diff -uNr src.old/novfs/blank.c src/novfs/blank.c +--- src.old/novfs/blank.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/blank.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,61 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: .c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module +- * +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +- +-/*===[ Include files specific to this module ]============================*/ +- +-/*===[ External data ]====================================================*/ +- +-/*===[ External prototypes ]==============================================*/ +- +-/*===[ Manifest constants ]===============================================*/ +- +-/*===[ Type definitions ]=================================================*/ +- +-/*===[ Function prototypes ]==============================================*/ +- +-/*===[ Global variables ]=================================================*/ +- +-/*===[ Code ]=============================================================*/ +- +-/*++======================================================================*/ +-Function +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +diff -uNr src.old/novfs/daemon.c src/novfs/daemon.c +--- src.old/novfs/daemon.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/daemon.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,2877 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: daemon.c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module contains all the functions necessary +- * for sending commands to our daemon module. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +- +-/*===[ Include files specific to this module ]============================*/ +-#include "vfs.h" +-#include "nwcapi.h" +-#include "commands.h" +-#include "nwerror.h" +- +-/*===[ External data ]====================================================*/ +-extern char *Novfs_CurrentMount; +-extern char DbgDaemonLogOn; +- +- +-/*===[ External prototypes ]==============================================*/ +-extern int DbgPrint( char *Fmt, ... ); +-extern void mydump(int size, void *dumpptr); +- +-extern char *Scope_Get_UserName( void *Scope ); +-extern void *Scope_Lookup( void ); +-extern session_t Scope_Get_SessionId( void *Scope ); +-extern void Scope_Cleanup( void ); +- +-extern int Novfs_Read_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId); +-extern int Novfs_Write_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); +-extern int Novfs_Close_Stream( u_long ConnHandle, u_char *Handle, session_t SessionId ); +- +-extern int Novfs_Add_to_Root(char *); +- +-/* +- * nwcapi.c functions +- */ +-extern int NwAuthConnWithId(PXPLAT pdata, session_t Session); +-extern int NwConnClose(PXPLAT pdata, u_long *Handle, session_t Session); +-extern int NwGetConnInfo(PXPLAT pdata, session_t Session); +-extern int NwSetConnInfo(PXPLAT pdata, session_t Session); +-extern int NwGetDaemonVersion(PXPLAT pdata, session_t Session); +-extern int NwGetIdentityInfo(PXPLAT pdata, session_t Session); +-extern int NwLicenseConn(PXPLAT pdata, session_t Session); +-extern int NwLoginIdentity(PXPLAT pdata, session_t Session); +-extern int NwLogoutIdentity(PXPLAT pdata, session_t Session); +-extern int NwOpenConnByAddr(PXPLAT pdata, u_long *Handle, session_t Session); +-extern int NwOpenConnByName(PXPLAT pdata, u_long *Handle, session_t Session); +-extern int NwOpenConnByRef(PXPLAT pdata, u_long *Handle, session_t Session); +-extern int NwQueryFeature(PXPLAT pdata, session_t Session); +-extern int NwRawSend(PXPLAT pdata, session_t Session); +-extern int NwScanConnInfo(PXPLAT pdata, session_t Session); +-extern int NwSysConnClose(PXPLAT pdata, u_long *Handle, session_t Session); +-extern int NwUnAuthenticate(PXPLAT pdata, session_t Session); +-extern int NwUnlicenseConn(PXPLAT pdata, session_t Session); +-extern int NwcChangeAuthKey(PXPLAT pdata, session_t Session); +-extern int NwcEnumIdentities(PXPLAT pdata, session_t Session); +-extern int NwcGetDefaultNameCtx(PXPLAT pdata, session_t Session); +-extern int NwcGetPreferredDSTree(PXPLAT pdata, session_t Session); +-extern int NwcGetTreeMonitoredConn(PXPLAT pdata, session_t Session); +-extern int NwcSetDefaultNameCtx(PXPLAT pdata, session_t Session); +-extern int NwcSetPreferredDSTree(PXPLAT pdata, session_t Session); +-extern int NwcSetPrimaryConn(PXPLAT pdata, session_t Session); +-extern int NwcGetPrimaryConn(PXPLAT pdata, session_t Session); +-extern int NwcSetMapDrive(PXPLAT pdata, session_t Session); +-extern int NwcUnMapDrive(PXPLAT pdata, session_t Session); +-extern int NwcEnumerateDrives(PXPLAT pdata, session_t Session); +-extern int NwcGetBroadcastMessage(PXPLAT pdata, session_t Session); +-extern int NwdSetKeyValue(PXPLAT pdata, session_t Session); +-extern int NwdVerifyKeyValue(PXPLAT pdata, session_t Session); +- +-/*===[ Manifest constants ]===============================================*/ +-#define QUEUE_SENDING 0 +-#define QUEUE_WAITING 1 +-#define QUEUE_TIMEOUT 2 +-#define QUEUE_ACKED 3 +-#define QUEUE_DONE 4 +- +-#define TIMEOUT_VALUE 10 +- +-#define DH_TYPE_UNDEFINED 0 +-#define DH_TYPE_STREAM 1 +-#define DH_TYPE_CONNECTION 2 +- +-/*===[ Type definitions ]=================================================*/ +-typedef struct _DAEMON_QUEUE +-{ +- struct list_head list; /* Must be first entry */ +- spinlock_t lock; /* Used to control access to list */ +- struct semaphore semaphore; /* Used to signal when data is available */ +-} daemon_queue_t; +- +-typedef struct _DAEMON_COMMAND +-{ +- struct list_head list; /* Must be first entry */ +- atomic_t reference; +- u_long status; +- u_long flags; +- struct semaphore semaphore; +- u_long sequence; +- struct timer_list timer; +- void *request; +- u_long reqlen; +- void *data; +- int datalen; +- void *reply; +- u_long replen; +-} daemon_command_t; +- +- +-typedef struct _DAEMON_HANDLE_ +-{ +- struct list_head list; +- rwlock_t lock; +- session_t session; +-} daemon_handle_t; +- +-typedef struct _DAEMON_RESOURCE_ +-{ +- struct list_head list; +- int type; +- u_long connection; +- u_char handle[6]; +- mode_t mode; +- loff_t size; +-} daemon_resource_t; +- +-typedef struct _DRIVE_MAP_ +-{ +- struct list_head list; /* Must be first item */ +- session_t session; +- u_long hash; +- int namelen; +- char name[1]; +-} drive_map_t; +- +-/*===[ Function prototypes ]==============================================*/ +-int Daemon_Added_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_char *FHandle, u_long Mode, u_long Size); +-int Daemon_Close_Control(struct inode *Inode, struct file *File); +-int Daemon_CreateSessionId( uint64_t *SessionId ); +-int Daemon_DestroySessionId( uint64_t SessionId ); +-void Daemon_Dumpque( void ); +-int Daemon_Get_UserSpace( uint64_t SessionId, uint64_t *TotalSize, uint64_t *TotalFree, uint64_t *TotalDirectoryEnties, uint64_t *FreeDirectoryEnties); +-int Daemon_Library_close(struct inode *inode, struct file *file); +-int Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg); +-int Daemon_Library_open(struct inode *inode, struct file *file); +-ssize_t Daemon_Library_read(struct file *file, char *buf, size_t len, loff_t *off); +-ssize_t Daemon_Library_write(struct file *file, const char *buf, size_t len, loff_t *off); +-loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin); +-int Daemon_Login(PLOGIN Login, session_t Session); +-int Daemon_Logout(PLOGOUT Logout, session_t Session); +-int Daemon_Open_Control(struct inode *Inode, struct file *File); +-uint Daemon_Poll(struct file *file, struct poll_table_struct *poll_table); +-ssize_t Daemon_Receive_Reply(struct file * file, char * buf, size_t nbytes, loff_t *ppos); +-int Daemon_Remove_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_long FHandle); +- +-ssize_t Daemon_Send_Command(struct file *file, char *buf, size_t len, loff_t *off); +-int Daemon_SetMountPoint( char *Path ); +-void Daemon_Timer(u_long data); +-int Daemon_getpwuid( uid_t uid, int unamelen, char *uname ); +-int Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg); +-void Init_Daemon_Queue( void ); +-int Queue_Daemon_Command(void *request, u_long reqlen, void *data, int dlen, void **reply, u_long *replen, int interruptible); +-void Queue_get(daemon_command_t *que); +-void Queue_put(daemon_command_t *que); +-void Uninit_Daemon_Queue( void ); +-int do_login(NclString *Server, NclString *Username, NclString *Password, u_long *lgnId, session_t Session); +-int do_logout( struct qstr *Server, session_t Session ); +-daemon_command_t *find_queue(u_long sequence); +-daemon_command_t *get_next_queue(int Set_Queue_Waiting); +-int NwdConvertNetwareHandle(PXPLAT pdata, daemon_handle_t *DHandle); +-int NwdConvertLocalHandle(PXPLAT pdata, daemon_handle_t *DHandle); +-int NwdGetMountPath(PXPLAT pdata); +-int NwdSetMapDrive(PXPLAT pdata, session_t Session); +-int NwdUnMapDrive(PXPLAT pdata, session_t Session); +-void RemoveDriveMaps( void ); +-int local_unlink(const char *pathname); +- +-/*===[ Global variables ]=================================================*/ +-daemon_queue_t Daemon_Queue; +- +-static DECLARE_WAIT_QUEUE_HEAD(Read_waitqueue); +- +-u_long Sequence = 0; +-atomic_t Daemon_Open_Count=ATOMIC_INIT(0); +- +-u_long Daemon_Command_Timeout = TIMEOUT_VALUE; +- +-DECLARE_MUTEX ( DriveMapLock ); +-LIST_HEAD( DriveMapList ); +- +-int MaxIoSize=PAGE_SIZE; +- +-/*===[ Code ]=============================================================*/ +- +-/*++======================================================================*/ +-void Init_Daemon_Queue() +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- INIT_LIST_HEAD(&Daemon_Queue.list); +- spin_lock_init(&Daemon_Queue.lock); +- init_MUTEX_LOCKED(&Daemon_Queue.semaphore); +-} +- +-/*++======================================================================*/ +-void Uninit_Daemon_Queue( void ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- /* Does nothing for now but we maybe should clear the queue. */ +-} +- +-/*++======================================================================*/ +-void +-NO_TRACE +-Daemon_Timer(u_long data) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que = (daemon_command_t *)data; +- +- if ( QUEUE_ACKED != que->status ) +- { +- que->status = QUEUE_TIMEOUT; +- } +- up(&que->semaphore); +-} +- +-/*++======================================================================*/ +-int Queue_Daemon_Command( +- void *request, +- u_long reqlen, +- void *data, +- int dlen, +- void **reply, +- u_long *replen, +- int interruptible) +-/* +- * +- * Arguments: void *request - pointer to the request that is to be sent. Needs to be kernel memory. +- * int reqlen - length of the request. +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- int retCode = 0; +- struct timespec ts1, ts2; +- +- ts1 = current_kernel_time(); +- +- DbgPrint( "Queue_Daemon_Command: 0x%x %d\n", request, reqlen); +- +- if (atomic_read(&Daemon_Open_Count)) +- { +- +- que = (daemon_command_t *)Novfs_Malloc(sizeof(*que), GFP_KERNEL); +- +- DbgPrint( "Queue_Daemon_Command: que=0x%x\n", que); +- if (que) +- { +- atomic_set( &que->reference, 0 ); +- que->status = QUEUE_SENDING; +- que->flags = 0; +- +- init_MUTEX_LOCKED(&que->semaphore); +- +- DbgPrint( "Queue_Daemon_Command: semaphore inited que=0x%x\n", que); +- +- que->sequence = InterlockedIncrement(&Sequence); +- +- DbgPrint( "Queue_Daemon_Command: sequence=0x%x\n", que->sequence); +- +- ((PCOMMAND_REQUEST_HEADER)request)->SequenceNumber = que->sequence; +- +- /* +- * Setup and start que timer +- */ +- init_timer(&que->timer); +- que->timer.expires = jiffies + (HZ * Daemon_Command_Timeout); +- que->timer.data = (u_long)que; +- que->timer.function = Daemon_Timer; +- add_timer(&que->timer); +- +- DbgPrint( "Queue_Daemon_Command: timer started que=0x%x\n", que); +- +- /* +- * Setup request +- */ +- que->request = request; +- que->reqlen = reqlen; +- que->data = data; +- que->datalen = dlen; +- que->reply = NULL; +- que->replen = 0; +- +- DbgPrint( "Queue_Daemon_Command: setting up que=0x%x\n", que); +- +- /* +- * Added entry to queue. +- */ +- DbgPrint( "Queue_Daemon_Command: Daemon_Queue locked\n"); +- +- /* +- * Check to see if interruptible and set flags. +- */ +- if (interruptible) +- { +- que->flags |= INTERRUPTIBLE; +- } +- +- spin_lock(&Daemon_Queue.lock); +- Queue_get( que ); +- list_add_tail(&que->list, &Daemon_Queue.list); +- spin_unlock(&Daemon_Queue.lock); +- +- DbgPrint( "Queue_Daemon_Command: 0x%x added to Daemon_Queue\n", que); +- /* +- * Signal that there is data to be read +- */ +- up(&Daemon_Queue.semaphore); +- +- /* +- * Give a change to the other processes. +- */ +- yield(); +- +- DbgPrint( "Queue_Daemon_Command: calling down 0x%x\n", CURRENT_TIME); +- +- /* +- * Block waiting for reply or timeout +- */ +- down(&que->semaphore); +- +- DbgPrint( "Queue_Daemon_Command: after down 0x%x\n", CURRENT_TIME); +- +- if ( QUEUE_ACKED == que->status ) +- { +- que->status = QUEUE_WAITING; +- mod_timer(&que->timer, jiffies + (HZ * 2 * Daemon_Command_Timeout)); +- DbgPrint( "Queue_Daemon_Command: mod_timer 0x%x\n", CURRENT_TIME); +- if (interruptible) +- { +- retCode = down_interruptible(&que->semaphore); +- } +- else +- { +- down(&que->semaphore); +- } +- DbgPrint( "Queue_Daemon_Command: after down2 0x%x\n", CURRENT_TIME); +- } +- +- DbgPrint( "Queue_Daemon_Command: after down 0x%d 0x%x\n", retCode, CURRENT_TIME); +- /* +- * Delete timer +- */ +- del_timer(&que->timer); +- +- /* +- * Check for timeout +- */ +- if ((QUEUE_TIMEOUT == que->status) && (NULL == que->reply) ) +- { +- DbgPrint( "Queue_Daemon_Command: Timeout\n"); +- retCode = -ETIME; +- } +- *reply = que->reply; +- *replen = que->replen; +- +- /* +- * Remove item from queue +- */ +- Queue_put( que ); +- +- } +- else /* Error case with no memory */ +- { +- retCode = -ENOMEM; +- *reply = NULL; +- *replen = 0; +- } +- } +- else +- { +- retCode = -EIO; +- *reply = NULL; +- *replen = 0; +- +- } +- ts2 = current_kernel_time(); +- if (ts2.tv_nsec < ts1.tv_nsec) +- { +- ts2.tv_sec--; +- ts2.tv_nsec += NSEC_PER_SEC; +- } +- ts2.tv_sec = ts2.tv_sec-ts1.tv_sec; +- ts2.tv_nsec = ts2.tv_nsec-ts1.tv_nsec; +- +- DbgPrint( "Queue_Daemon_Command: %ld:%lu retCode=%d \n", ts2.tv_sec, ts2.tv_nsec, retCode); +- return(retCode); +-} +- +-/*++======================================================================*/ +-void Queue_get(daemon_command_t *Que) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DbgPrint("Queue_get: que=0x%p %d\n", Que, atomic_read(&Que->reference)); +- atomic_inc( &Que->reference ); +-} +- +-/*++======================================================================*/ +-void Queue_put(daemon_command_t *Que) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- spin_lock(&Daemon_Queue.lock); +- +- DbgPrint("Queue_put: que=0x%p %d\n", Que, atomic_read(&Que->reference)); +- if ( atomic_dec_and_test( &Que->reference )) +- { +- /* +- * Remove item from queue +- */ +- list_del(&Que->list); +- +- spin_unlock(&Daemon_Queue.lock); +- +- /* +- * Free item memory +- */ +- Novfs_Free(Que); +- } +- else +- { +- spin_unlock(&Daemon_Queue.lock); +- } +-} +- +-/*++======================================================================*/ +-daemon_command_t *get_next_queue(int Set_Queue_Waiting) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- +- spin_lock(&Daemon_Queue.lock); +- que = (daemon_command_t *)Daemon_Queue.list.next; +- +- DbgPrint( "get_next_queue: que=0x%x\n", que); +- +- while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next) && ( que->status != QUEUE_SENDING ) ) +- { +- que = (daemon_command_t *)que->list.next; +- DbgPrint( "get_next_queue: que1=0x%x\n", que); +- } +- +- if ((NULL == que) || (que == (daemon_command_t *)&Daemon_Queue.list) || (que->status != QUEUE_SENDING)) +- { +- que = NULL; +- } +- else if (Set_Queue_Waiting) +- { +- que->status = QUEUE_WAITING; +- } +- +- if (que) +- { +- atomic_inc( &que->reference ); +- } +- +- spin_unlock(&Daemon_Queue.lock); +- +- DbgPrint( "get_next_queue: return=0x%x\n", que); +- return(que); +-} +- +-/*++======================================================================*/ +-daemon_command_t *find_queue(u_long sequence) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- +- DbgPrint( "find_queue: 0x%x\n", sequence); +- +- spin_lock(&Daemon_Queue.lock); +- que = (daemon_command_t *)Daemon_Queue.list.next; +- +- DbgPrint( "find_queue: que=0x%x\n", que); +- +- while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next) && (que->sequence != sequence)) +- { +- DbgPrint( "find_queue: que1=0x%x\n", que); +- que = (daemon_command_t *)que->list.next; +- } +- +- if ((NULL == que) || (que == (daemon_command_t *)&Daemon_Queue.list.next) || (que->sequence != sequence)) +- { +- que = NULL; +- } +- +- if (que) +- { +- atomic_inc( &que->reference ); +- } +- +- spin_unlock(&Daemon_Queue.lock); +- +- DbgPrint( "find_queue: return 0x%x\n", que); +- return(que); +-} +-/*++======================================================================*/ +-int Daemon_Open_Control(struct inode *Inode, struct file *File) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DbgPrint("Daemon_Open_Control: pid=%d Count=%d\n", current->pid, atomic_read(&Daemon_Open_Count)); +- atomic_inc(&Daemon_Open_Count); +- +- return(0); +-} +- +-/*++======================================================================*/ +-int Daemon_Close_Control(struct inode *Inode, struct file *File) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- +- DbgPrint("Daemon_Close_Control: pid=%d Count=%d\n", current->pid, atomic_read(&Daemon_Open_Count)); +- +- if (atomic_dec_and_test(&Daemon_Open_Count)) +- { +- /* +- * Signal any pending que itmes. +- */ +- +- spin_lock(&Daemon_Queue.lock); +- que = (daemon_command_t *)Daemon_Queue.list.next; +- +- DbgPrint( "Daemon_Close_Control: que=0x%x\n", que); +- +- while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next) && (que->status != QUEUE_DONE)) +- { +- que->status = QUEUE_TIMEOUT; +- up(&que->semaphore); +- +- que = (daemon_command_t *)que->list.next; +- DbgPrint( "Daemon_Close_Control: que1=0x%x\n", que); +- } +- spin_unlock(&Daemon_Queue.lock); +- +- RemoveDriveMaps(); +- +- Scope_Cleanup(); +- } +- +- return(0); +-} +- +-/*++======================================================================*/ +-ssize_t +-Daemon_Send_Command(struct file *file, char *buf, size_t len, loff_t *off) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- size_t retValue = 0; +- int Finished=0; +- PDATA_LIST dlist; +- int i, dcnt, bcnt, ccnt, error; +- char *vadr; +- u_long cpylen; +- +- DbgPrint( "Daemon_Send_Command: %u %lld\n", len, *off); +- if (len > MaxIoSize) +- { +- MaxIoSize = len; +- } +- +- while ( !Finished ) +- { +- que = get_next_queue(1); +- DbgPrint( "Daemon_Send_Command: 0x%x\n", que); +- if (que) +- { +- retValue = que->reqlen; +- if (retValue > len) +- { +- retValue = len; +- } +- if (retValue > 0x80) +- mydump(0x80, que->request); +- else +- mydump(retValue, que->request); +- +- cpylen = copy_to_user(buf, que->request, retValue); +- if (que->datalen && (retValue < len)) +- { +- buf += retValue; +- dlist = que->data; +- dcnt = que->datalen; +- for (i=0; irwflag ) +- { +- bcnt = dlist->len; +- DbgPrint("Daemon_Send_Command%d: page=0x%x offset=0x%x len=%d\n", i, dlist->page, dlist->offset, dlist->len); +- if ((bcnt + retValue) <= len) +- { +- void *km_adr=NULL; +- +- if (dlist->page) +- { +- //vadr = kmap(dlist->page); +- km_adr = kmap_atomic(dlist->page, KM_USER1); +- vadr = km_adr; +- vadr += (u_int)dlist->offset; +- } +- else +- { +- vadr = dlist->offset; +- } +- +- ccnt = copy_to_user(buf, vadr, bcnt); +- +- if ( km_adr ) +- { +- //kunmap(dlist->page); +- kunmap_atomic(km_adr, KM_USER1); +- } +- +- DbgPrint("Daemon_Send_Command: Copy %d from 0x%x to 0x%x.\n", bcnt, vadr, buf); +- if (bcnt > 0x80) +- mydump(0x80, vadr); +- else +- mydump(bcnt, vadr); +- +- retValue += bcnt; +- buf += bcnt; +- } +- else +- { +- break; +- } +- } +- } +- } +- Queue_put( que ); +- break; +- } +- +- if (O_NONBLOCK & file->f_flags) +- { +- retValue = -EAGAIN; +- break; +- } +- else +- { +- if ((error = down_interruptible(&Daemon_Queue.semaphore))) +- { +- DbgPrint( "Daemon_Send_Command: after down_interruptible error...%d\n", error); +- retValue = -EINTR; +- break; +- } +- DbgPrint( "Daemon_Send_Command: after down_interruptible\n"); +- } +- } +- +- *off = *off; +- +- DbgPrint( "Daemon_Send_Command: return 0x%x\n", retValue); +- +- return(retValue); +-} +- +-/*++======================================================================*/ +-ssize_t +-Daemon_Receive_Reply(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- size_t retValue = 0; +- void *reply; +- u_long sequence, cpylen; +- +- PDATA_LIST dlist; +- char *vadr; +- int i; +- +- DbgPrint( "Daemon_Receive_Reply: buf=0x%x nbytes=%d ppos=%llx\n", buf, nbytes, *ppos); +- +- /* +- * Get sequence number from reply buffer +- */ +- +- cpylen = copy_from_user(&sequence, buf, sizeof(sequence)); +- +- /* +- * Find item based on sequence number +- */ +- que = find_queue(sequence); +- +- DbgPrint( "Daemon_Receive_Reply: 0x%x 0x%x %d\n", sequence, que, nbytes); +- if (que) +- { +- do +- { +- retValue = nbytes; +- /* +- * Ack packet from novfsd. Remove timer and +- * return +- */ +- if (nbytes == sizeof(sequence)) +- { +- que->status = QUEUE_ACKED; +- break; +- } +- +- /* +- * Set status that packet is done. +- */ +- que->status = QUEUE_DONE; +- +- if ( NULL != (dlist = que->data) ) +- { +- int thiscopy, left=nbytes; +- retValue = 0; +- +- +- DbgPrint( "Daemon_Receive_Reply: dlist=0x%x count=%d\n", dlist, que->datalen); +- for (i=0; i < que->datalen; i++, dlist++) +- { +- DbgPrint( "Daemon_Receive_Reply:\n" \ +- " dlist[%d].page: 0x%x\n" \ +- " dlist[%d].offset: 0x%x\n" \ +- " dlist[%d].len: 0x%x\n" \ +- " dlist[%d].rwflag: 0x%x\n", +- i, dlist->page, +- i, dlist->offset, +- i, dlist->len, +- i, dlist->rwflag); +- +- if (DLWRITE == dlist->rwflag) +- { +- void *km_adr=NULL; +- +- if (dlist->page) +- { +- //vadr = kmap(dlist->page); +- km_adr = kmap_atomic(dlist->page, KM_USER1); +- vadr = km_adr; +- vadr += (u_int)dlist->offset; +- } +- else +- { +- vadr = dlist->offset; +- } +- +- thiscopy = dlist->len; +- if (thiscopy > left) +- { +- thiscopy = left; +- dlist->len = left; +- } +- cpylen = copy_from_user(vadr, buf, thiscopy); +- +- if ( km_adr ) +- { +- //kunmap(dlist->page); +- kunmap_atomic(km_adr, KM_USER1); +- } +- +- left -= thiscopy; +- retValue += thiscopy; +- buf += thiscopy; +- } +- } +- } +- else +- { +- reply = Novfs_Malloc(nbytes, GFP_KERNEL); +- DbgPrint( "Daemon_Receive_Reply: reply=0x%x\n", reply); +- if (reply) +- { +- retValue = nbytes; +- que->reply = reply; +- que->replen = nbytes; +- +- retValue -= copy_from_user(reply, buf, retValue); +- if (retValue > 0x80) +- mydump(0x80, reply); +- else +- mydump(retValue, reply); +- +- +- } +- else +- { +- retValue = -ENOMEM; +- } +- } +- } while (0); +- up(&que->semaphore); +- Queue_put( que ); +- } +- +- DbgPrint( "Daemon_Receive_Reply: return 0x%x\n", retValue); +- +- return(retValue); +-} +- +-/*++======================================================================*/ +-int do_login(NclString *Server, NclString *Username, NclString *Password, u_long *lgnId, session_t Session) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PLOGIN_USER_REQUEST cmd; +- PLOGIN_USER_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen, datalen; +- u_char *data; +- +- datalen = Server->len+Username->len+Password->len; +- cmdlen = sizeof(*cmd) + datalen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- data = (u_char *)cmd + sizeof(*cmd); +- cmd->Command.CommandType = VFS_COMMAND_LOGIN_USER; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- +- cmd->srvNameType = Server->type; +- cmd->serverLength = Server->len; +- cmd->serverOffset = (u_long)(data-(u_char *)cmd); +- memcpy(data, Server->buffer, Server->len); +- data += Server->len; +- +- cmd->usrNameType = Username->type; +- cmd->userNameLength = Username->len; +- cmd->userNameOffset = (u_long)(data-(u_char *)cmd); +- memcpy(data, Username->buffer, Username->len); +- data += Username->len; +- +- cmd->pwdNameType = Password->type; +- cmd->passwordLength = Password->len; +- cmd->passwordOffset = (u_long)(data-(u_char *)cmd); +- memcpy(data, Password->buffer, Password->len); +- data += Password->len; +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- retCode = reply->Reply.ErrorCode; +- } +- else +- { +- retCode = 0; +- if (lgnId) +- { +- *lgnId = reply->loginIdentity; +- } +- } +- Novfs_Free(reply); +- } +- memset(cmd, 0, cmdlen); +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +- +-} +- +-/*++======================================================================*/ +-int do_logout( struct qstr *Server, session_t Session ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PLOGOUT_REQUEST cmd; +- PLOGOUT_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen; +- +- cmdlen = (int)(&((PLOGOUT_REQUEST)0)->Name) + Server->len; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_LOGOUT_USER; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- +- cmd->Length = Server->len; +- memcpy(cmd->Name, Server->name, Server->len); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +- +-} +- +-/*++======================================================================*/ +-int Daemon_getpwuid( uid_t uid, int unamelen, char *uname ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- GETPWUID_REQUEST cmd; +- PGETPWUID_REPLY reply; +- u_long replylen=0; +- int retCode; +- +- cmd.Command.CommandType = VFS_COMMAND_GETPWUD; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = 0; +- cmd.uid = uid; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- else +- { +- retCode = 0; +- memset(uname, 0, unamelen); +- replylen = replylen - (int)(&((PGETPWUID_REPLY)0)->UserName); +- if (replylen) +- { +- if (replylen > unamelen) +- { +- retCode = -EINVAL; +- replylen = unamelen-1; +- } +- memcpy(uname, reply->UserName, replylen); +- } +- } +- Novfs_Free(reply); +- } +- return( retCode ); +- +-} +- +-/*++======================================================================*/ +-int Daemon_getversion( char *Buf, int Length ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- GET_VERSION_REQUEST cmd; +- PGET_VERSION_REPLY reply; +- u_long replylen=0; +- int retVal=0; +- +- cmd.Command.CommandType = VFS_COMMAND_GET_VERSION; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = 0; +- +- Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- retVal = -EIO; +- } +- else +- { +- retVal = replylen - (int)(&((PGET_VERSION_REPLY)0)->Version); +- if (retVal < Length) +- { +- memcpy(Buf, reply->Version, retVal); +- Buf[retVal] = '\0'; +- } +- } +- Novfs_Free(reply); +- } +- return( retVal ); +- +-} +- +-/*++======================================================================*/ +-int Daemon_Login(PLOGIN Login, session_t Session) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOMEM; +- LOGIN lLogin; +- NclString server; +- NclString username; +- NclString password; +- +- if ( !copy_from_user(&lLogin, Login, sizeof(lLogin))) +- { +- if ( (server.buffer = Novfs_Malloc(lLogin.Server.Length, GFP_KERNEL)) ) +- { +- server.len = lLogin.Server.Length; +- server.type = NWC_STRING_TYPE_ASCII; +- if ( !copy_from_user((void *)server.buffer, lLogin.Server.Data, server.len) ) +- { +- if ( (username.buffer = Novfs_Malloc(lLogin.UserName.Length, GFP_KERNEL)) ) +- { +- username.len = lLogin.UserName.Length; +- username.type = NWC_STRING_TYPE_ASCII; +- if ( !copy_from_user((void *)username.buffer, lLogin.UserName.Data, username.len) ) +- { +- if ( (password.buffer = Novfs_Malloc(lLogin.Password.Length, GFP_KERNEL)) ) +- { +- password.len = lLogin.Password.Length; +- password.type = NWC_STRING_TYPE_ASCII; +- if ( !copy_from_user((void *)password.buffer, lLogin.Password.Data, password.len) ) +- { +- retCode = do_login(&server, &username, &password, NULL, Session); +- if ( !retCode ) +- { +- char *username; +- username = Scope_Get_UserName( NULL ); +- if (username) +- { +- Novfs_Add_to_Root( username ); +- } +- } +- } +- memset(password.buffer, 0, password.len); +- Novfs_Free(password.buffer); +- } +- } +- memset(username.buffer, 0, username.len); +- Novfs_Free(username.buffer); +- } +- } +- Novfs_Free(server.buffer); +- } +- } +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Daemon_Logout(PLOGOUT Logout, session_t Session) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- LOGOUT lLogout; +- struct qstr server; +- int retCode=0; +- +- if ( !copy_from_user(&lLogout, Logout, sizeof(lLogout))) +- { +- if ( (server.name = Novfs_Malloc(lLogout.Server.Length, GFP_KERNEL)) ) +- { +- server.len = lLogout.Server.Length; +- if ( !copy_from_user((void *)server.name, lLogout.Server.Data, server.len) ) +- { +- retCode = do_logout( &server, Session ); +- } +- Novfs_Free(server.name); +- } +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Daemon_CreateSessionId( uint64_t *SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- CREATE_CONTEXT_REQUEST cmd; +- PCREATE_CONTEXT_REPLY reply; +- u_long replylen=0; +- int retCode=0; +- +- DbgPrint("Daemon_CreateSessionId: %d\n", current->pid); +- +- cmd.Command.CommandType = VFS_COMMAND_CREATE_CONTEXT; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = 0; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- if ( !reply->Reply.ErrorCode && replylen > sizeof(COMMAND_REPLY_HEADER)) +- { +- *SessionId = reply->SessionId; +- retCode = 0; +- } +- else +- { +- *SessionId = 0; +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- DbgPrint("Daemon_CreateSessionId: SessionId=0x%llx\n", *SessionId); +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Daemon_DestroySessionId( uint64_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DESTROY_CONTEXT_REQUEST cmd; +- PDESTROY_CONTEXT_REPLY reply; +- u_long replylen=0; +- int retCode=0; +- +- DbgPrint("Daemon_DestroySessionId: 0x%llx\n", SessionId); +- +- cmd.Command.CommandType = VFS_COMMAND_DESTROY_CONTEXT; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- if ( !reply->Reply.ErrorCode ) +- { +- drive_map_t *dm; +- struct list_head *list; +- +- retCode = 0; +- +- /* +- * When destroying the session check to see if there are any +- * mapped drives. If there are then remove them. +- */ +- down( &DriveMapLock ); +- list_for_each( list, &DriveMapList ) +- { +- dm = list_entry( list, drive_map_t, list ); +- if ( SessionId == dm->session) +- { +- local_unlink( dm->name ); +- list = list->prev; +- list_del( &dm->list ); +- Novfs_Free( dm ); +- } +- +- } +- up( &DriveMapLock ); +- +- } +- else +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Daemon_Get_UserSpace( uint64_t SessionId, uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- GET_USER_SPACE_REQUEST cmd; +- PGET_USER_SPACE_REPLY reply; +- u_long replylen=0; +- int retCode=0; +- +- DbgPrint("Daemon_Get_UserSpace: 0x%llx\n", SessionId); +- +- cmd.Command.CommandType = VFS_COMMAND_GET_USER_SPACE; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- if ( !reply->Reply.ErrorCode ) +- { +- +- DbgPrint("TotalSpace: %llu\n", reply->TotalSpace); +- DbgPrint("FreeSpace: %llu\n", reply->FreeSpace); +- DbgPrint("TotalEnties: %llu\n", reply->TotalEnties); +- DbgPrint("FreeEnties: %llu\n", reply->FreeEnties); +- +- if (TotalSize) *TotalSize = reply->TotalSpace; +- if (Free) *Free = reply->FreeSpace; +- if (TotalEnties) *TotalEnties = reply->TotalEnties; +- if (FreeEnties) *FreeEnties = reply->FreeEnties; +- retCode = 0; +- } +- else +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Daemon_SetMountPoint ( char *Path ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSET_MOUNT_PATH_REQUEST cmd; +- PSET_MOUNT_PATH_REPLY reply; +- u_long replylen, cmdlen; +- int retCode = -ENOMEM; +- +- DbgPrint("Daemon_SetMountPoint: %s\n", Path); +- +- replylen = strlen(Path); +- +- cmdlen = sizeof(SET_MOUNT_PATH_REQUEST) + replylen; +- +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if ( cmd ) +- { +- cmd->Command.CommandType = VFS_COMMAND_SET_MOUNT_PATH; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = 0; +- cmd->PathLength = replylen; +- +- strcpy(cmd->Path, Path); +- +- replylen = 0; +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- if ( !reply->Reply.ErrorCode ) +- { +- retCode = 0; +- } +- else +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Daemon_SendDebugCmd ( char *Command ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DEBUG_REQUEST cmd; +- PDEBUG_REPLY reply; +- DEBUG_REPLY lreply; +- u_long replylen, cmdlen; +- DATA_LIST dlist[2]; +- +- int retCode = -ENOMEM; +- +- DbgPrint("Daemon_SendDebugCmd: %s\n", Command); +- +- dlist[0].page = NULL; +- dlist[0].offset = (char *)Command; +- dlist[0].len = strlen(Command); +- dlist[0].rwflag = DLREAD; +- +- dlist[1].page = NULL; +- dlist[1].offset = (char *)&lreply; +- dlist[1].len = sizeof(lreply); +- dlist[1].rwflag = DLWRITE; +- +- cmdlen = (int)(&((PDEBUG_REQUEST)0)->dbgcmd); +- +- cmd.Command.CommandType = VFS_COMMAND_DBG; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = 0; +- cmd.cmdlen = strlen(Command); +- +- replylen = 0; +- +- retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, 2, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- Novfs_Free(reply); +- } +- if (0 == retCode) +- { +- retCode = lreply.Reply.ErrorCode; +- } +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-int +-NO_TRACE +-Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOSYS; +- u_long cpylen; +- +- +- switch (cmd) +- { +- case IOC_LOGIN: +- { +- retCode = Daemon_Login((PLOGIN)arg, Scope_Get_SessionId( NULL )); +- break; +- } +- +- case IOC_LOGOUT: +- { +- retCode = Daemon_Logout((PLOGOUT)arg, Scope_Get_SessionId( NULL )); +- break; +- } +- case IOC_DEBUGPRINT: +- { +- struct Ioctl_Debug { +- int length; +- char *data; +- } io; +- char *buf; +- io.length = 0; +- cpylen = copy_from_user(&io, (char *)arg, sizeof(io)); +- if (io.length) +- { +- buf = Novfs_Malloc(io.length+1, GFP_KERNEL); +- if (buf) +- { +- buf[0] = 0; +- cpylen = copy_from_user(buf, io.data, io.length); +- buf[io.length] = '\0'; +- if( DbgDaemonLogOn ) +- printk("%s", buf); +- else +- DbgPrint("%s", buf); +- Novfs_Free(buf); +- retCode = 0; +- } +- } +- break; +- } +- +- case IOC_XPLAT: +- { +- XPLAT data; +- +- cpylen = copy_from_user(&data, (void *)arg, sizeof(data)); +- retCode = ((data.xfunction & 0x0000FFFF) | 0xCC000000); +- +- switch(data.xfunction) +- { +- case NWC_GET_MOUNT_PATH: +- DbgPrint("[Daemon_ioctl] Call NwdGetMountPath\n"); +- retCode = NwdGetMountPath( &data ); +- break; +- } +- +- DbgPrint("[NOVFS XPLAT] status Code = %X\n", retCode); +- break; +- } +- +- } +- return (retCode); +-} +- +-/*++======================================================================*/ +-int Daemon_Added_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_char *FHandle, u_long Mode, u_long Size) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_resource_t *resource; +- int retVal = NWE_OUT_OF_HEAP_SPACE; +- +- if (FHandle) +- DbgPrint("Daemon_Added_Resource: DHandle=0x%p Type=%d CHandle=0x%x FHandle=0x%x Mode=0x%x Size=%d\n", DHandle, Type, CHandle, *(u_long *)&FHandle[2], Mode, Size); +- else +- DbgPrint("Daemon_Added_Resource: DHandle=0x%p Type=%d CHandle=0x%x\n", DHandle, Type, CHandle); +- +- resource = Novfs_Malloc(sizeof(daemon_resource_t), GFP_KERNEL); +- if (resource) +- { +- resource->type = Type; +- resource->connection = CHandle; +- if (FHandle) +- { +- memcpy( resource->handle, FHandle, sizeof(resource->handle) ); +- } +- else +- { +- memset( resource->handle, 0, sizeof(resource->handle) ); +- } +- resource->mode = Mode; +- resource->size = Size; +- write_lock( &DHandle->lock ); +- list_add( &resource->list, &DHandle->list ); +- write_unlock( &DHandle->lock ); +- DbgPrint("Daemon_Added_Resource: Adding resource=0x%p\n", resource); +- retVal = 0; +- } +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int Daemon_Remove_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_long FHandle) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_resource_t *resource; +- struct list_head *l; +- int retVal = -ENOMEM; +- +- DbgPrint("Daemon_Remove_Resource: DHandle=0x%p Type=%d CHandle=0x%x FHandle=0x%x\n", DHandle, Type, CHandle, FHandle); +- +- write_lock( &DHandle->lock ); +- +- list_for_each( l, &DHandle->list ) +- { +- resource = list_entry( l, daemon_resource_t, list ); +- +- if ( (Type == resource->type) && +- (resource->connection == CHandle) ) +- { +- DbgPrint("Daemon_Remove_Resource: Found resource=0x%p\n", resource); +- l = l->prev; +- list_del( &resource->list ); +- Novfs_Free( resource ); +- break; +- } +- } +- +- write_unlock( &DHandle->lock ); +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int Daemon_Library_open(struct inode *inode, struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal = -ENOMEM; +- daemon_handle_t *dh; +- +- DbgPrint("Daemon_Library_open: inode=0x%p file=0x%p\n", inode, file); +- +- if ((dh = Novfs_Malloc(sizeof(daemon_handle_t), GFP_KERNEL))) +- { +- file->private_data = dh; +- INIT_LIST_HEAD( &dh->list); +- rwlock_init( &dh->lock ); +- dh->session = Scope_Get_SessionId( NULL ); +- retVal = 0; +- } +- return(retVal); +-} +- +-/*++======================================================================*/ +-int Daemon_Library_close(struct inode *inode, struct file *file) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_handle_t *dh; +- daemon_resource_t *resource; +- struct list_head *l; +- +- char commanddata[sizeof(XPLAT_CALL_REQUEST)+sizeof(NwdCCloseConn)]; +- PXPLAT_CALL_REQUEST cmd; +- PXPLAT_CALL_REPLY reply; +- PNwdCCloseConn nwdClose; +- u_long cmdlen, replylen; +- +- DbgPrint("Daemon_Library_close: inode=0x%p file=0x%p\n", inode, file); +- if (file->private_data) +- { +- dh = (daemon_handle_t *)file->private_data; +- +- list_for_each( l, &dh->list ) +- { +- resource = list_entry( l, daemon_resource_t, list ); +- +- if (DH_TYPE_STREAM == resource->type) +- { +- Novfs_Close_Stream( resource->connection, resource->handle, dh->session ); +- } +- else if (DH_TYPE_CONNECTION == resource->type) +- { +- cmd = (PXPLAT_CALL_REQUEST)commanddata; +- cmdlen = offsetof(XPLAT_CALL_REQUEST, data) + sizeof(NwdCCloseConn); +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = dh->session; +- cmd->NwcCommand = NWC_CLOSE_CONN; +- +- cmd->dataLen = sizeof(NwdCCloseConn); +- nwdClose = (PNwdCCloseConn)cmd->data; +- nwdClose->ConnHandle = resource->connection; +- +- Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, 0); +- if (reply) +- { +- Novfs_Free(reply); +- } +- } +- l = l->prev; +- list_del( &resource->list ); +- Novfs_Free( resource ); +- } +- Novfs_Free(dh); +- file->private_data = NULL; +- } +- +- return(0); +-} +- +-/*++======================================================================*/ +-ssize_t Daemon_Library_read(struct file *file, char *buf, size_t len, loff_t *off) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_handle_t *dh; +- daemon_resource_t *resource; +- +- size_t thisread, totalread=0; +- loff_t offset = *off; +- +- DbgPrint("Daemon_Library_read: file=0x%p len=%d off=%lld\n", file, len, *off); +- +- if (file->private_data) +- { +- dh = file->private_data; +- read_lock( &dh->lock ); +- if (&dh->list != dh->list.next) +- { +- resource = list_entry( dh->list.next, daemon_resource_t, list ); +- +- if (DH_TYPE_STREAM == resource->type) +- { +- while( len > 0 && (offset < resource->size) ) +- { +- thisread = len; +- if (Novfs_Read_Stream(resource->connection, +- resource->handle, +- buf, &thisread, +- &offset, 1, +- dh->session) || !thisread) +- { +- break; +- } +- len -= thisread; +- buf += thisread; +- offset += thisread; +- totalread += thisread; +- } +- } +- } +- read_unlock( &dh->lock ); +- } +- *off = offset; +- DbgPrint("Daemon_Library_read return = 0x%x\n", totalread); +- return(totalread); +-} +- +-/*++======================================================================*/ +-ssize_t Daemon_Library_write(struct file *file, const char *buf, size_t len, loff_t *off) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_handle_t *dh; +- daemon_resource_t *resource; +- +- size_t thiswrite, totalwrite=-EINVAL; +- loff_t offset = *off; +- int status; +- +- DbgPrint("Daemon_Library_write: file=0x%p len=%d off=%lld\n", file, len, *off); +- +- if (file->private_data) +- { +- dh = file->private_data; +- write_lock( &dh->lock ); +- if (&dh->list != dh->list.next) +- { +- resource = list_entry( dh->list.next, daemon_resource_t, list ); +- +- if ( (DH_TYPE_STREAM == resource->type) && (len >= 0) ) +- { +- totalwrite = 0; +- do +- { +- thiswrite = len; +- status = Novfs_Write_Stream(resource->connection, +- resource->handle, +- (PVOID)buf, +- &thiswrite, +- &offset, +- dh->session); +- if ( status || !thiswrite ) +- { +- /* +- * If len is zero then the file will have just been +- * truncated to offset. Update size. +- */ +- if ( !status && !len ) +- { +- resource->size = offset; +- } +- totalwrite = status; +- break; +- } +- len -= thiswrite; +- buf += thiswrite; +- offset += thiswrite; +- totalwrite += thiswrite; +- if (offset > resource->size) +- { +- resource->size = offset; +- } +- } while(len > 0); +- } +- } +- write_unlock( &dh->lock ); +- } +- *off = offset; +- DbgPrint("Daemon_Library_write return = 0x%x\n", totalwrite); +- +- return(totalwrite); +-} +- +-/*++======================================================================*/ +-loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_handle_t *dh; +- daemon_resource_t *resource; +- +- loff_t retVal = -EINVAL; +- +- DbgPrint("Daemon_Library_llseek: file=0x%p offset=%lld origin=%d\n", file, offset, origin); +- +- if (file->private_data) +- { +- dh = file->private_data; +- read_lock( &dh->lock ); +- if (&dh->list != dh->list.next) +- { +- resource = list_entry( dh->list.next, daemon_resource_t, list ); +- +- if (DH_TYPE_STREAM == resource->type) +- { +- switch (origin) { +- case 2: +- offset += resource->size; +- break; +- case 1: +- offset += file->f_pos; +- } +- if (offset >= 0) { +- if (offset != file->f_pos) { +- file->f_pos = offset; +- file->f_version = 0; +- } +- retVal = offset; +- } +- } +- } +- read_unlock( &dh->lock ); +- } +- +- DbgPrint("Daemon_Library_llseek: ret %lld\n", retVal); +- +- return retVal; +-} +- +-/*++======================================================================*/ +-int +-NO_TRACE +-Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOSYS; +- daemon_handle_t *dh; +- u_long handle=0, cpylen; +- +- +- dh = file->private_data; +- +- DbgPrint("Daemon_Library_ioctl: file=0x%p 0x%x 0x%x dh=0x%p\n", file, cmd, arg, dh); +- +- if (dh) +- { +- +- switch (cmd) +- { +- case IOC_LOGIN: +- { +- retCode = Daemon_Login((PLOGIN)arg, dh->session); +- break; +- } +- +- case IOC_LOGOUT: +- { +- retCode = Daemon_Logout((PLOGOUT)arg, dh->session); +- break; +- } +- +- case IOC_DEBUGPRINT: +- { +- struct Ioctl_Debug { +- int length; +- char *data; +- } io; +- char *buf; +- io.length = 0; +- cpylen = copy_from_user(&io, (char *)arg, sizeof(io)); +- if (io.length) +- { +- buf = Novfs_Malloc(io.length+1, GFP_KERNEL); +- if (buf) +- { +- buf[0] = 0; +- cpylen = copy_from_user(buf, io.data, io.length); +- buf[io.length] = '\0'; +- DbgPrint("%s", buf); +- Novfs_Free(buf); +- retCode = 0; +- } +- } +- break; +- } +- +- case IOC_XPLAT: +- { +- XPLAT data; +- +- cpylen = copy_from_user(&data, (void *)arg, sizeof(data)); +- retCode = ((data.xfunction & 0x0000FFFF) | 0xCC000000); +- +- switch(data.xfunction) +- { +- case NWC_OPEN_CONN_BY_NAME: +- DbgPrint("[VFS XPLAT] Call NwOpenConnByName\n"); +- retCode = NwOpenConnByName(&data, &handle, dh->session); +- if ( !retCode ) +- { +- Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, 0, 0, 0); +- } +- break; +- +- case NWC_OPEN_CONN_BY_ADDRESS: +- DbgPrint("[VFS XPLAT] Call NwOpenConnByAddress\n"); +- retCode = NwOpenConnByAddr(&data, &handle, dh->session); +- if ( !retCode ) +- { +- Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, 0, 0, 0); +- } +- break; +- +- case NWC_OPEN_CONN_BY_REFERENCE: +- +- DbgPrint("[VFS XPLAT] Call NwOpenConnByReference\n"); +- retCode = NwOpenConnByRef(&data, &handle, dh->session); +- if ( !retCode ) +- { +- Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, 0, 0, 0); +- } +- break; +- +- case NWC_SYS_CLOSE_CONN: +- DbgPrint("[VFS XPLAT] Call NwSysCloseConn\n"); +- retCode = NwSysConnClose(&data, &handle, dh->session); +- Daemon_Remove_Resource(dh, DH_TYPE_CONNECTION, handle, 0); +- break; +- +- case NWC_CLOSE_CONN: +- DbgPrint("[VFS XPLAT] Call NwCloseConn\n"); +- retCode = NwConnClose(&data, &handle, dh->session); +- Daemon_Remove_Resource(dh, DH_TYPE_CONNECTION, handle, 0); +- break; +- +- case NWC_LOGIN_IDENTITY: +- DbgPrint("[VFS XPLAT] Call NwLoginIdentity\n"); +- retCode = NwLoginIdentity(&data, dh->session); +- break; +- +- case NWC_RAW_NCP_REQUEST: +- DbgPrint("[VFS XPLAT] Send Raw NCP Request\n"); +- retCode = NwRawSend(&data, dh->session); +- break; +- +- case NWC_AUTHENTICATE_CONN_WITH_ID: +- DbgPrint("[VFS XPLAT] Authenticate Conn With ID\n"); +- retCode = NwAuthConnWithId(&data, dh->session); +- break; +- +- case NWC_UNAUTHENTICATE_CONN: +- DbgPrint("[VFS XPLAT] UnAuthenticate Conn With ID\n"); +- retCode = NwUnAuthenticate(&data, dh->session); +- break; +- +- case NWC_LICENSE_CONN: +- DbgPrint("Call NwLicenseConn\n"); +- retCode = NwLicenseConn(&data, dh->session); +- break; +- +- case NWC_LOGOUT_IDENTITY: +- DbgPrint("[VFS XPLAT] Call NwLogoutIdentity\n"); +- retCode = NwLogoutIdentity(&data, dh->session); +- break; +- +- case NWC_UNLICENSE_CONN: +- DbgPrint("[VFS XPLAT] Call NwUnlicense\n"); +- retCode = NwUnlicenseConn(&data, dh->session); +- break; +- +- case NWC_GET_CONN_INFO: +- DbgPrint("[VFS XPLAT] Call NwGetConnInfo\n"); +- retCode = NwGetConnInfo(&data, dh->session); +- break; +- +- case NWC_SET_CONN_INFO: +- DbgPrint("[VFS XPLAT] Call NwGetConnInfo\n"); +- retCode = NwSetConnInfo(&data, dh->session); +- break; +- +- case NWC_SCAN_CONN_INFO: +- DbgPrint("[VFS XPLAT] Call NwScanConnInfo\n"); +- retCode = NwScanConnInfo(&data, dh->session); +- break; +- +- +- case NWC_GET_IDENTITY_INFO: +- DbgPrint("[VFS XPLAT] Call NwGetIdentityInfo\n"); +- retCode = NwGetIdentityInfo(&data, dh->session); +- break; +- +- case NWC_GET_REQUESTER_VERSION: +- DbgPrint("[VFS XPLAT] Call NwGetDaemonVersion\n"); +- retCode = NwGetDaemonVersion(&data, dh->session); +- break; +- +- case NWC_GET_PREFERRED_DS_TREE: +- DbgPrint("[VFS XPLAT] Call NwcGetPreferredDsTree\n"); +- retCode = NwcGetPreferredDSTree(&data, dh->session); +- break; +- +- case NWC_SET_PREFERRED_DS_TREE: +- DbgPrint("[VFS XPLAT] Call NwcSetPreferredDsTree\n"); +- retCode = NwcSetPreferredDSTree(&data, dh->session); +- break; +- +- case NWC_GET_DEFAULT_NAME_CONTEXT: +- DbgPrint("[VFS XPLAT] Call NwcGetDefaultNameContext\n"); +- retCode = NwcGetDefaultNameCtx(&data, dh->session); +- break; +- +- case NWC_SET_DEFAULT_NAME_CONTEXT: +- DbgPrint("[VFS XPLAT] Call NwcSetDefaultNameContext\n"); +- retCode = NwcSetDefaultNameCtx(&data, dh->session); +- break; +- +- case NWC_QUERY_FEATURE: +- DbgPrint("[VFS XPLAT] Call NwQueryFeature\n"); +- retCode = NwQueryFeature(&data, dh->session); +- break; +- +- +- case NWC_GET_TREE_MONITORED_CONN_REF: +- DbgPrint("[VFS XPLAT] Call NwcGetTreeMonitoredConn\n"); +- retCode = NwcGetTreeMonitoredConn(&data, dh->session); +- break; +- +- case NWC_ENUMERATE_IDENTITIES: +- DbgPrint("[VFS XPLAT] Call NwcEnumerateIdentities\n"); +- retCode = NwcEnumIdentities(&data, dh->session); +- break; +- +- case NWC_CHANGE_KEY: +- DbgPrint("[VFS XPLAT] Call NwcChangeAuthKey\n"); +- retCode = NwcChangeAuthKey(&data, dh->session); +- break; +- +- case NWC_CONVERT_LOCAL_HANDLE: +- DbgPrint("[VFS XPLAT] Call NwdConvertLocalHandle\n"); +- retCode = NwdConvertLocalHandle(&data, dh); +- break; +- +- case NWC_CONVERT_NETWARE_HANDLE: +- DbgPrint("[VFS XPLAT] Call NwdConvertNetwareHandle\n"); +- retCode = NwdConvertNetwareHandle(&data, dh); +- break; +- +- case NWC_SET_PRIMARY_CONN: +- DbgPrint("[VFS XPLAT] Call NwcSetPrimaryConn\n"); +- retCode = NwcSetPrimaryConn(&data, dh->session); +- break; +- +- case NWC_GET_PRIMARY_CONN: +- DbgPrint("[VFS XPLAT] Call NwcGetPrimaryConn\n"); +- retCode = NwcGetPrimaryConn(&data, dh->session); +- break; +- +- case NWC_MAP_DRIVE: +- DbgPrint("[VFS XPLAT] Call NwcMapDrive\n"); +- retCode = NwdSetMapDrive(&data, dh->session); +- break; +- +- case NWC_UNMAP_DRIVE: +- DbgPrint("[VFS XPLAT] Call NwcUnMapDrive\n"); +- retCode = NwdUnMapDrive(&data, dh->session); +- break; +- +- case NWC_ENUMERATE_DRIVES: +- DbgPrint("[VFS XPLAT] Call NwcEnumerateDrives\n"); +- retCode = NwcEnumerateDrives(&data, dh->session); +- break; +- +- case NWC_GET_MOUNT_PATH: +- DbgPrint("[VFS XPLAT] Call NwdGetMountPath\n"); +- retCode = NwdGetMountPath( &data ); +- break; +- +- case NWC_GET_BROADCAST_MESSAGE: +- DbgPrint("[VSF XPLAT Call NwdGetBroadcastMessage\n"); +- retCode = NwcGetBroadcastMessage(&data, dh->session); +- break; +- +- case NWC_SET_KEY: +- DbgPrint("[VSF XPLAT Call NwdSetKey\n"); +- retCode = NwdSetKeyValue(&data, dh->session); +- break; +- +- case NWC_VERIFY_KEY: +- DbgPrint("[VSF XPLAT Call NwdVerifyKey\n"); +- retCode = NwdVerifyKeyValue(&data, dh->session); +- break; +- +- case NWC_RAW_NCP_REQUEST_ALL: +- case NWC_NDS_RESOLVE_NAME_TO_ID: +- case NWC_FRAGMENT_REQUEST: +- case NWC_GET_CONFIGURED_NSPS: +- default: +- break; +- +- } +- +- DbgPrint("[NOVFS XPLAT] status Code = %X\n", retCode); +- break; +- } +- } +- } +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-unsigned int Daemon_Poll(struct file *file, struct poll_table_struct *poll_table) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- daemon_command_t *que; +- unsigned int mask = POLLOUT | POLLWRNORM; +- +- que = get_next_queue(0); +- if (que) +- { +- mask |= (POLLIN | POLLRDNORM); +- } +- else +- { +- +- } +- return(mask); +-} +- +- +-void Daemon_Dumpque( void ) +-{ +-#ifdef CONFIG_KDB +- daemon_command_t *que; +- +- que = (daemon_command_t *)Daemon_Queue.list.next; +- +- while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next)) +- { +- kdb_printf("DaemonQue:\n" \ +- " Que: 0x%p\n" \ +- " status: 0x%lx\n" \ +- " flags: 0x%lx\n" \ +- " semaphore: 0x%x\n" \ +- " sequence: 0x%lx\n" \ +- " timer: 0x%lx\n" \ +- " request: 0x%p\n" \ +- " reqlen: %ld\n" \ +- " data: 0x%p\n" \ +- " datalen: %d\n" \ +- " reply: 0x%p\n" \ +- " replen: %ld\n", +- que, +- que->status, +- que->flags, +- atomic_read(&que->semaphore.count), +- que->sequence, +- que->timer.expires, +- que->request, +- que->reqlen, +- que->data, +- que->datalen, +- que->reply, +- que->replen); +- que = (daemon_command_t *)que->list.next; +- } +-#endif +-} +- +-/*++======================================================================*/ +-int NwdConvertNetwareHandle(PXPLAT pdata, daemon_handle_t *DHandle) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal; +- NwcConvertNetWareHandle nh; +- u_long cpylen; +- +- DbgPrint("NwdConvertNetwareHandle: DHandle=0x%p\n", DHandle); +- +- cpylen = copy_from_user(&nh, pdata->reqData, sizeof(NwcConvertNetWareHandle)); +- +- retVal = Daemon_Added_Resource(DHandle, DH_TYPE_STREAM, nh.ConnHandle, nh.NetWareHandle, nh.uAccessMode, nh.uFileSize); +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int NwdConvertLocalHandle(PXPLAT pdata, daemon_handle_t *DHandle) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal = NWE_REQUESTER_FAILURE; +- daemon_resource_t *resource; +- NwcConvertLocalHandle lh; +- struct list_head *l; +- u_long cpylen; +- +- DbgPrint("NwdConvertLocalHandle: DHandle=0x%p\n", DHandle); +- +- read_lock( &DHandle->lock ); +- +- list_for_each( l, &DHandle->list ) +- { +- resource = list_entry( l, daemon_resource_t, list ); +- +- if ( DH_TYPE_STREAM == resource->type ) +- { +- lh.uConnReference = resource->connection; +- +- memcpy(lh.NwFileHandle, resource->handle, sizeof(resource->handle)); +- if (pdata->repLen >= sizeof(NwcConvertLocalHandle)) +- { +- cpylen = copy_to_user(pdata->repData, &lh, sizeof(NwcConvertLocalHandle)); +- retVal = 0; +- } +- else +- { +- retVal = NWE_BUFFER_OVERFLOW; +- } +- break; +- } +- } +- +- read_unlock( &DHandle->lock ); +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int NwdGetMountPath(PXPLAT pdata) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal = NWE_REQUESTER_FAILURE; +- int len; +- u_long cpylen; +- NwcGetMountPath mp; +- +- cpylen = copy_from_user(&mp, pdata->reqData, pdata->reqLen); +- +- if ( Novfs_CurrentMount ) +- { +- +- len = strlen(Novfs_CurrentMount)+1; +- if ( (len > mp.MountPathLen) && mp.pMountPath) +- { +- retVal = NWE_BUFFER_OVERFLOW; +- } +- else +- { +- if (mp.pMountPath) +- { +- cpylen = copy_to_user(mp.pMountPath, Novfs_CurrentMount, len); +- } +- retVal = 0; +- } +- +- mp.MountPathLen = len; +- +- if (pdata->repData && (pdata->repLen >= sizeof(mp)) ) +- { +- cpylen = copy_to_user(pdata->repData, &mp, sizeof(mp)); +- } +- } +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int NwdSetMapDrive(PXPLAT pdata, session_t Session) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal; +- u_long cpylen; +- +- retVal = NwcSetMapDrive(pdata, Session); +- if ( !retVal ) +- { +- NwcMapDriveEx symInfo; +- char *path; +- drive_map_t *drivemap, *dm; +- struct list_head *list; +- +- cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); +- drivemap = Novfs_Malloc( sizeof(drive_map_t)+symInfo.linkOffsetLength, GFP_KERNEL ); +- if (drivemap) +- { +- path = (char *)pdata->reqData; +- path += symInfo.linkOffset; +- cpylen = copy_from_user(drivemap->name, path, symInfo.linkOffsetLength); +- +- drivemap->session = Session; +- drivemap->hash = full_name_hash(drivemap->name, symInfo.linkOffsetLength-1); +- drivemap->namelen = symInfo.linkOffsetLength-1; +- DbgPrint( "NwdSetMapDrive: hash=0x%x path=%s\n", drivemap->hash, drivemap->name); +- +- dm = (drive_map_t *)&DriveMapList.next; +- +- down( &DriveMapLock ); +- +- list_for_each( list, &DriveMapList ) +- { +- dm = list_entry( list, drive_map_t, list ); +- DbgPrint( "NwdSetMapDrive: dm=0x%p\n" \ +- " hash: 0x%x\n" \ +- " namelen: %d\n" \ +- " name: %s\n", +- dm, dm->hash, dm->namelen, dm->name); +- +- if (drivemap->hash == dm->hash) +- { +- if ( 0 == strcmp(dm->name, drivemap->name)) +- { +- dm = NULL; +- break; +- } +- } +- else if (drivemap->hash < dm->hash) +- { +- break; +- } +- } +- +- if (dm) +- { +- if ( (dm == (drive_map_t *)&DriveMapList) || +- (dm->hash < drivemap->hash) ) +- { +- list_add( &drivemap->list, &dm->list); +- } +- else +- { +- list_add_tail( &drivemap->list, &dm->list); +- } +- } +- else +- { +- Novfs_Free( drivemap ); +- } +- up( &DriveMapLock ); +- } +- } +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int NwdUnMapDrive(PXPLAT pdata, session_t Session) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal = NWE_REQUESTER_FAILURE; +- u_long cpylen; +- +- retVal = NwcUnMapDrive(pdata, Session); +- if ( !retVal ) +- { +- NwcUnmapDriveEx symInfo; +- char *path; +- drive_map_t *dm; +- struct list_head *list; +- u_long hash; +- +- +- cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); +- path = Novfs_Malloc( symInfo.linkLen, GFP_KERNEL ); +- if (path) +- { +- cpylen = copy_from_user(path, ((NwcUnmapDriveEx *)pdata->reqData)->linkData, symInfo.linkLen); +- +- hash = full_name_hash(path, symInfo.linkLen-1); +- DbgPrint( "NwdUnMapDrive: hash=0x%x path=%s\n", hash, path); +- +- dm = NULL; +- +- down( &DriveMapLock ); +- +- list_for_each( list, &DriveMapList ) +- { +- dm = list_entry( list, drive_map_t, list ); +- DbgPrint( "NwdUnMapDrive: dm=0x%p %s\n" \ +- " hash: 0x%x\n" \ +- " namelen: %d\n", +- dm, dm->name, dm->hash, dm->namelen); +- +- if (hash == dm->hash) +- { +- if ( 0 == strcmp(dm->name, path)) +- { +- break; +- } +- } +- else if (hash < dm->hash) +- { +- dm = NULL; +- break; +- } +- } +- +- if (dm) +- { +- DbgPrint( "NwdUnMapDrive: Remove dm=0x%p %s\n" \ +- " hash: 0x%x\n" \ +- " namelen: %d\n", +- dm, dm->name, dm->hash, dm->namelen); +- list_del( &dm->list ); +- Novfs_Free( dm ); +- } +- +- up( &DriveMapLock ); +- } +- } +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-void RemoveDriveMaps( void ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- drive_map_t *dm; +- struct list_head *list; +- +- down( &DriveMapLock ); +- list_for_each( list, &DriveMapList ) +- { +- dm = list_entry( list, drive_map_t, list ); +- +- DbgPrint( "RemoveDriveMap: dm=0x%p\n" \ +- " hash: 0x%x\n" \ +- " namelen: %d\n" \ +- " name: %s\n", +- dm, dm->hash, dm->namelen, dm->name); +- local_unlink( dm->name ); +- list = list->prev; +- list_del( &dm->list ); +- Novfs_Free( dm ); +- } +- up( &DriveMapLock ); +-} +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +-/*++======================================================================*/ +-int local_unlink(const char *pathname) +-{ +- int error; +- struct dentry *dentry; +- struct nameidata nd; +- struct inode *inode = NULL; +- +- DbgPrint("local_unlink: %s\n", pathname); +- error = path_lookup(pathname, LOOKUP_PARENT, &nd); +- DbgPrint("local_unlink: path_lookup %d\n", error); +- if ( !error ) +- { +- error = -EISDIR; +- if (nd.last_type == LAST_NORM) +- { +- mutex_lock(&nd.dentry->d_inode->i_mutex); +- dentry = lookup_hash( &nd ); +- DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry); +- +- error = PTR_ERR(dentry); +- if (!IS_ERR(dentry)) +- { +- if (nd.last.name[nd.last.len]) +- { +- error = !dentry->d_inode ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; +- } +- else +- { +- inode = dentry->d_inode; +- if (inode) +- { +- atomic_inc(&inode->i_count); +- } +- error = vfs_unlink(nd.dentry->d_inode, dentry); +- DbgPrint("local_unlink: vfs_unlink %d\n", error); +- } +- dput(dentry); +- } +- mutex_unlock(&nd.dentry->d_inode->i_mutex); +- +- } +- path_release(&nd); +- } +- +- if (inode) +- { +- iput(inode); /* truncate the inode here */ +- } +- +- DbgPrint("local_unlink: error=%d\n", error); +- return error; +-} +- +-#else +-/*++======================================================================*/ +-int local_unlink(const char *pathname) +-{ +- int error; +- struct dentry *dentry; +- struct nameidata nd; +- struct inode *inode = NULL; +- +- DbgPrint("local_unlink: %s\n", pathname); +- error = path_lookup(pathname, LOOKUP_PARENT, &nd); +- DbgPrint("local_unlink: path_lookup %d\n", error); +- if ( !error ) +- { +- error = -EISDIR; +- if (nd.last_type == LAST_NORM) +- { +- down(&nd.dentry->d_inode->i_sem); +- dentry = lookup_hash(&nd.last, nd.dentry); +- DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry); +- +- error = PTR_ERR(dentry); +- if (!IS_ERR(dentry)) +- { +- if (nd.last.name[nd.last.len]) +- { +- error = !dentry->d_inode ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; +- } +- else +- { +- inode = dentry->d_inode; +- if (inode) +- { +- atomic_inc(&inode->i_count); +- } +- error = vfs_unlink(nd.dentry->d_inode, dentry); +- DbgPrint("local_unlink: vfs_unlink %d\n", error); +- } +- dput(dentry); +- } +- up(&nd.dentry->d_inode->i_sem); +- } +- path_release(&nd); +- } +- +- if (inode) +- { +- iput(inode); /* truncate the inode here */ +- } +- +- DbgPrint("local_unlink: error=%d\n", error); +- return error; +-} +-#endif +diff -uNr src.old/novfs/file.c src/novfs/file.c +--- src.old/novfs/file.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/file.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,2188 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: file.c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module contains functions for accessing +- * files through the daemon. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/*===[ Include files specific to this module ]============================*/ +-#include "commands.h" +-#include "nwerror.h" +-#include "vfs.h" +- +-/*===[ External data ]====================================================*/ +-extern struct dentry_operations Novfs_dentry_operations; +- +-/*===[ External prototypes ]==============================================*/ +-extern int DbgPrint( char *Fmt, ... ); +-extern void mydump(int size, void *dumpptr); +-extern int Queue_Daemon_Command(void *request, u_long reqlen, void *data, int dlen, void **reply, u_long *replen, int interruptible); +-extern struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t uid); +- +-extern void *Scope_Lookup( void ); +- +-/*===[ Manifest constants ]===============================================*/ +- +-/*===[ Type definitions ]=================================================*/ +- +-/*===[ Function prototypes ]==============================================*/ +- +-int Novfs_verify_file( struct qstr *Path, session_t SessionId ); +-int Novfs_get_alltrees(struct dentry *parent); +-ssize_t Novfs_tree_read(struct file *file, char *buf, size_t len, loff_t *off); +- +-int Novfs_Get_Connected_Server_List( u_char **ServerList, session_t SessionId ); +-int Novfs_Get_Server_Volume_List( struct qstr *Server, u_char **VolumeList, session_t SessionId ); +-int Novfs_Find_Name_In_List( struct qstr *Name, u_char *List ); +-int Novfs_Verify_Server_Name( struct qstr *Server, session_t SessionId ); +-int Novfs_Verify_Volume_Name( struct qstr *Server, struct qstr *Volume, session_t SessionId ); +-int Novfs_Get_File_Info( u_char *Path, PENTRY_INFO Info, session_t SessionId ); +-int Novfs_Get_Directory_List( u_char *Path, u_long *EnumHandle, PENTRY_INFO Info, session_t SessionId ); +-int Novfs_Get_Directory_ListEx( u_char *Path, u_long *EnumHandle, int *Count, PENTRY_INFO *Info, session_t SessionId ); +-int Novfs_Open_File( u_char *Path, int Flags, PENTRY_INFO Info, u_long *Handle, session_t SessionId ); +-int Novfs_Create( u_char *Path, int DirectoryFlag, session_t SessionId ); +-int Novfs_Close_File( u_long Handle, session_t SessionId ); +-int Novfs_Read_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId); +-int Novfs_Write_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); +-int Novfs_Read_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId); +-int Novfs_Write_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); +-int Novfs_Close_Stream( u_long ConnHandle, u_char *Handle, session_t SessionId ); +-int Novfs_Delete( u_char *Path, int DirectoryFlag, session_t SessionId ); +-int Novfs_Truncate_File( u_char *Path, int PathLen, session_t SessionId ); +-int Novfs_Rename_File( int DirectoryFlag, u_char *OldName, int OldLen, u_char *NewName, int NewLen, session_t SessionId ); +-int Novfs_Set_Attr( u_char *Path, struct iattr *Attr, session_t SessionId ); +- +-/*===[ Global variables ]=================================================*/ +-static struct file_operations Novfs_tree_operations = { +- read: Novfs_tree_read, +-}; +- +-/* +- * StripTrailingDots was added because some apps will +- * try and create a file name with a trailing dot. NetWare +- * doesn't like this and will return an error. +- */ +-u_char StripTrailingDots=1; +- +-/*===[ Code ]=============================================================*/ +- +-/*++======================================================================*/ +-int Novfs_verify_file( struct qstr *Path, scope_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PVERIFY_FILE_REPLY reply=NULL; +- u_long replylen=0; +- PVERIFY_FILE_REQUEST cmd; +- int cmdlen; +- int retCode=0; +- +- cmdlen = (int)(&((PVERIFY_FILE_REQUEST)0)->path) + Path->len; +- cmd = (PVERIFY_FILE_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- cmd->pathLen = Path->len; +- memcpy(cmd->path, Path->name, Path->len); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- DbgPrint("Novfs_verify_file: reply\n"); +- mydump(replylen, reply); +- if (reply->Reply.ErrorCode) +- { +- retCode = -ENOENT; +- } +- else +- { +- retCode = 0; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_get_alltrees(struct dentry *parent) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- u_char *p; +- PCOMMAND_REPLY_HEADER reply=NULL; +- u_long replylen=0; +- COMMAND_REQUEST_HEADER cmd; +- int retCode; +- struct dentry *entry; +- struct qstr name; +- struct inode *inode; +- +- cmd.CommandType = 0; +- cmd.SequenceNumber = 0; +- cmd.SessionId = 0x1234; +- +- DbgPrint( "Novfs_get_alltrees:\n"); +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- DbgPrint( "Novfs_get_alltrees: relpy=0x%x replylen=%d\n", reply, replylen); +- if (reply) +- { +- mydump(replylen, reply); +- if ( !reply->ErrorCode && (replylen > sizeof(COMMAND_REPLY_HEADER))) +- { +- p = (char *)reply+8; +- while (*p) +- { +- DbgPrint( "Novfs_get_alltrees: %s\n",p); +- name.len = strlen(p); +- name.name = p; +- name.hash = full_name_hash(name.name, name.len); +- entry = d_lookup(parent, &name); +- if ( NULL == entry ) +- { +- DbgPrint( "Novfs_get_alltrees: adding %s\n",p); +- entry = d_alloc(parent, &name); +- if (entry) +- { +- entry->d_op = &Novfs_dentry_operations; +- inode = Novfs_get_inode(parent->d_sb, S_IFREG | 0400, 0, 0); +- if (inode) +- { +- inode->i_fop = &Novfs_tree_operations; +- d_add(entry, inode); +- } +- } +- } +- p += (name.len+1); +- } +- } +- Novfs_Free(reply); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-ssize_t Novfs_tree_read(struct file *file, char *buf, size_t len, loff_t *off) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- if (file->f_pos != 0) +- { +- return(0); +- } +- if (copy_to_user(buf, "Tree\n", 5)) +- { +- return(0); +- } +- return(5); +-} +- +-/*++======================================================================*/ +-int Novfs_Get_Connected_Server_List( u_char **ServerList, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- GET_CONNECTED_SERVER_LIST_REQUEST req; +- PGET_CONNECTED_SERVER_LIST_REPLY reply=NULL; +- u_long replylen=0; +- int retCode=0; +- +- *ServerList = NULL; +- +- req.Command.CommandType = VFS_COMMAND_GET_CONNECTED_SERVER_LIST; +- req.Command.SessionId = SessionId; +- +- retCode = Queue_Daemon_Command(&req, sizeof(req), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- DbgPrint("Novfs_Get_Connected_Server_List: reply\n"); +- replylen -= sizeof(COMMAND_REPLY_HEADER); +- if ( !reply->Reply.ErrorCode && replylen ) +- { +- memcpy(reply, reply->List, replylen); +- *ServerList = (u_char *)reply; +- retCode = 0; +- } +- else +- { +- Novfs_Free(reply); +- retCode = -ENOENT; +- } +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Get_Server_Volume_List( struct qstr *Server, u_char **VolumeList, scope_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PGET_SERVER_VOLUME_LIST_REQUEST req; +- PGET_SERVER_VOLUME_LIST_REPLY reply=NULL; +- u_long replylen=0, reqlen; +- int retCode; +- +- *VolumeList = NULL; +- reqlen = sizeof(GET_SERVER_VOLUME_LIST_REQUEST)+Server->len; +- req = Novfs_Malloc(reqlen, GFP_KERNEL); +- if (req) +- { +- req->Command.CommandType = VFS_COMMAND_GET_SERVER_VOLUME_LIST; +- req->Length = Server->len; +- memcpy(req->Name, Server->name, Server->len); +- req->Command.SessionId = SessionId; +- +- retCode = Queue_Daemon_Command(req, reqlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if ( reply ) +- { +- DbgPrint("Novfs_Get_Server_Volume_List: reply\n"); +- mydump(replylen, reply); +- replylen -= sizeof(COMMAND_REPLY_HEADER); +- +- if ( !reply->Reply.ErrorCode && replylen ) +- { +- memcpy(reply, reply->List, replylen); +- *VolumeList = (u_char *)reply; +- retCode = 0; +- } +- else +- { +- Novfs_Free(reply); +- retCode = -ENOENT; +- } +- } +- Novfs_Free(req); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Find_Name_In_List( struct qstr *Name, u_char *List ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int len; +- int retCode = 0; +- +- while (*List) +- { +- len = strlen(List); +- if ((len == Name->len) && !strncmp(Name->name, List, len)) +- { +- retCode = 1; +- break; +- } +- List += (len+1); +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Verify_Server_Name( struct qstr *Server, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- u_char *list; +- int retCode = 0; +- +- DbgPrint("Novfs_Verify_Server_Name: %.*s\n", Server->len, Server->name); +- +- list = NULL; +- Novfs_Get_Connected_Server_List( &list, SessionId ); +- +- if (list) +- { +- retCode = Novfs_Find_Name_In_List( Server, list ); +- Novfs_Free(list); +- } +- DbgPrint("Novfs_Verify_Server_Name: %d\n", retCode); +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Verify_Volume_Name( struct qstr *Server, struct qstr *Volume, session_t SessionId ) +-/* +- * +- * Arguments: Server - Server name. +- * Volume - Volume name to check for. +- * +- * Returns: zero - not found. +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- u_char *list; +- int retCode = 0; +- u_char *name; +- int namelen; +- struct qstr path; +- +- list = NULL; +- namelen = Server->len+Volume->len+2; +- name = Novfs_Malloc(namelen, GFP_KERNEL); +- +- if (name) +- { +- name[0] = '\\'; +- memcpy(&name[1], Server->name, Server->len); +- name[1+Server->len] = '\\'; +- memcpy(&name[2+Server->len], Volume->name, Volume->len); +- path.len = namelen; +- path.name = name; +- +- if (Novfs_verify_file(&path, SessionId)) +- { +- retCode = 0; +- } +- else +- { +- retCode = 1; +- } +- +- Novfs_Free(name); +- } +- else +- { +- +- Novfs_Get_Server_Volume_List( Server, &list, SessionId ); +- +- if (list) +- { +- retCode = Novfs_Find_Name_In_List( Volume, list ); +- Novfs_Free(list); +- } +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Get_File_Info( u_char *Path, PENTRY_INFO Info, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PVERIFY_FILE_REPLY reply=NULL; +- u_long replylen=0; +- PVERIFY_FILE_REQUEST cmd; +- int cmdlen; +- int retCode=-ENOENT; +- int pathlen; +- +- DbgPrint("Novfs_Get_File_Info: Path = %s\n", Path); +- +- Info->mode = S_IFDIR | 0700; +- Info->uid = current->uid; +- Info->gid = current->gid; +- Info->size = 0; +- Info->atime = Info->mtime = Info->ctime = CURRENT_TIME; +- +- if (Path && *Path) +- { +- pathlen = strlen(Path); +- if (StripTrailingDots) +- { +- if ('.' == Path[pathlen-1]) pathlen--; +- } +- cmdlen = (int)(&((PVERIFY_FILE_REQUEST)0)->path) + pathlen; +- cmd = (PVERIFY_FILE_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- cmd->pathLen = pathlen; +- memcpy(cmd->path, Path, cmd->pathLen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +-/* +- * retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, 0); +- */ +- if (reply) +- { +- +- if ( reply->Reply.ErrorCode ) +- { +- retCode = -ENOENT; +- } +- else +- { +- Info->type = 3; +- Info->mode = S_IRWXU; +- +- if (reply->fileMode & NW_ATTRIBUTE_DIRECTORY) +- { +- Info->mode |= S_IFDIR; +- } +- else +- { +- Info->mode |= S_IFREG; +- } +- +- if (reply->fileMode & NW_ATTRIBUTE_READ_ONLY) +- { +- Info->mode &= ~(S_IWUSR); +- } +- +- Info->uid = current->euid; +- Info->gid = current->egid; +- Info->size = reply->fileSize; +- Info->atime.tv_sec = reply->lastAccessTime; +- Info->atime.tv_nsec = 0; +- Info->mtime.tv_sec = reply->modifyTime; +- Info->mtime.tv_nsec = 0; +- Info->ctime.tv_sec = reply->createTime; +- Info->ctime.tv_nsec = 0; +- retCode = 0; +- } +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- } +- +- DbgPrint("Novfs_Get_File_Info: return 0x%x\n", retCode); +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Get_File_Info2( u_char *Path, PENTRY_INFO Info, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PVERIFY_FILE_REPLY reply=NULL; +- u_long replylen=0; +- PVERIFY_FILE_REQUEST cmd; +- int cmdlen; +- struct qstr server = {0}, volume = {0}; +- u_char *p; +- int i; +- int retCode=-ENOENT; +- p = Path; +- +- DbgPrint("Novfs_Get_File_Info: Path = %s\n", Path); +- +- Info->mode = S_IFDIR | 0700; +- Info->uid = current->uid; +- Info->gid = current->gid; +- Info->size = 0; +- Info->atime = Info->mtime = Info->ctime = CURRENT_TIME; +- +- if ('\\' == *p) +- { +- p++; +- } +- server.name = p; +- +- for(i=0; *p && ('\\' != *p); i++, p++); +- server.len = i; +- if (*p) +- { +- if ('\\' == *p) +- { +- p++; +- } +- volume.name = p; +- for(i=0; *p && ('\\' != *p); i++, p++); +- if (i) +- { +- volume.len = i; +- if (*p) +- { +- if ('\\' == *p) +- { +- p++; +- } +- if (*p) +- { +- cmdlen = (int)(&((PVERIFY_FILE_REQUEST)0)->path) + strlen(Path); +- cmd = (PVERIFY_FILE_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- cmd->pathLen = strlen(Path); +- memcpy(cmd->path, Path, cmd->pathLen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- +- if ( reply->Reply.ErrorCode ) +- { +- retCode = -ENOENT; +- } +- else +- { +- Info->type = 3; +- Info->mode = S_IRWXU; +- +- if (reply->fileMode & NW_ATTRIBUTE_DIRECTORY) +- { +- Info->mode |= S_IFDIR; +- } +- else +- { +- Info->mode |= S_IFREG; +- } +- +- if (reply->fileMode & NW_ATTRIBUTE_READ_ONLY) +- { +- Info->mode &= ~(S_IWUSR); +- } +- +- Info->uid = current->euid; +- Info->gid = current->egid; +- Info->size = reply->fileSize; +- Info->atime.tv_sec = reply->lastAccessTime; +- Info->atime.tv_nsec = 0; +- Info->mtime.tv_sec = reply->modifyTime; +- Info->mtime.tv_nsec = 0; +- Info->ctime.tv_sec = reply->createTime; +- Info->ctime.tv_nsec = 0; +- retCode = 0; +- } +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- } +- } +- } +- if (('\0' == *p) && volume.len) +- { +- if ( Novfs_Verify_Volume_Name( &server, &volume, SessionId ) ) +- { +- retCode = 0; +- Info->type = 2; +- } +- } +- } +- if (server.len && !volume.len) +- { +- if ( Novfs_Verify_Server_Name( &server, SessionId ) ) +- { +- retCode = 0; +- Info->type = 1; +- } +- } +- DbgPrint("Novfs_Get_File_Info: return 0x%x\n", retCode); +- return(retCode); +-} +- +-/*++======================================================================*/ +-int begin_directory_enumerate( u_char *Path, int PathLen, u_long *EnumHandle, session_t SessionId) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PBEGIN_ENUMERATE_DIRECTORY_REQUEST cmd; +- PBEGIN_ENUMERATE_DIRECTORY_REPLY reply=NULL; +- u_long replylen=0; +- int retCode, cmdlen; +- +- *EnumHandle = 0; +- +- cmdlen = (int)(&((PBEGIN_ENUMERATE_DIRECTORY_REQUEST)0)->path) + PathLen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_START_ENUMERATE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->pathLen = PathLen; +- memcpy(cmd->path, Path, PathLen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +-/* +- * retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, 0); +- */ +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- else +- { +- *EnumHandle = reply->enumerateHandle; +- retCode = 0; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int end_directory_enumerate( u_long EnumHandle, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- END_ENUMERATE_DIRECTORY_REQUEST cmd; +- PEND_ENUMERATE_DIRECTORY_REPLY reply=NULL; +- u_long replylen=0; +- int retCode; +- +- +- cmd.Command.CommandType = VFS_COMMAND_END_ENUMERATE; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.enumerateHandle = EnumHandle; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, 0); +- if (reply) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int directory_enumerate( u_long *EnumHandle, PENTRY_INFO Info, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- ENUMERATE_DIRECTORY_REQUEST cmd; +- PENUMERATE_DIRECTORY_REPLY reply=NULL; +- u_long replylen=0; +- int retCode; +- +- +- cmd.Command.CommandType = VFS_COMMAND_ENUMERATE_DIRECTORY; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.enumerateHandle = *EnumHandle; +- cmd.pathLen = 0; +- cmd.path[0] = '\0'; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- /* +- * The VFS_COMMAND_ENUMERATE_DIRECTORY call can return an +- * error but there could still be valid data. +- */ +- if ( !reply->Reply.ErrorCode || +- ( (replylen > sizeof(COMMAND_REPLY_HEADER)) && +- (reply->nameLen > 0)) ) +- { +- Info->type = 3; +- Info->mode = S_IRWXU; +- +- if (reply->mode & NW_ATTRIBUTE_DIRECTORY) +- { +- Info->mode |= S_IFDIR; +- Info->mode |= S_IXUSR; +- } +- else +- { +- Info->mode |= S_IFREG; +- } +- +- if (reply->mode & NW_ATTRIBUTE_READ_ONLY) +- { +- Info->mode &= ~(S_IWUSR); +- } +- +- if (reply->mode & NW_ATTRIBUTE_EXECUTE) +- { +- Info->mode |= S_IXUSR; +- } +- +- Info->uid = current->uid; +- Info->gid = current->gid; +- Info->size = reply->size; +- Info->atime.tv_sec = reply->lastAccessTime; +- Info->atime.tv_nsec = 0; +- Info->mtime.tv_sec = reply->modifyTime; +- Info->mtime.tv_nsec = 0; +- Info->ctime.tv_sec = reply->createTime; +- Info->ctime.tv_nsec = 0; +- Info->namelength = reply->nameLen; +- memcpy(Info->name, reply->name, reply->nameLen); +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -1; /* Eof of data */ +- } +- *EnumHandle = reply->enumerateHandle; +- } +- else +- { +- retCode = -ENODATA; +- } +- Novfs_Free(reply); +- } +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int directory_enumerate_ex( u_long *EnumHandle, session_t SessionId, int *Count, PENTRY_INFO *PInfo, int Interrupt) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- ENUMERATE_DIRECTORY_EX_REQUEST cmd; +- PENUMERATE_DIRECTORY_EX_REPLY reply=NULL; +- u_long replylen=0; +- int retCode=0; +- PENTRY_INFO info; +- PENUMERATE_DIRECTORY_EX_DATA data; +- int isize; +- +- if (PInfo) +- { +- *PInfo = NULL; +- } +- *Count = 0; +- +- cmd.Command.CommandType = VFS_COMMAND_ENUMERATE_DIRECTORY_EX; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.enumerateHandle = *EnumHandle; +- cmd.pathLen = 0; +- cmd.path[0] = '\0'; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, Interrupt); +- +- if (reply) +- { +- retCode = 0; +- /* +- * The VFS_COMMAND_ENUMERATE_DIRECTORY call can return an +- * error but there could still be valid data. +- */ +- +- if ( !reply->Reply.ErrorCode || +- ( (replylen > sizeof(COMMAND_REPLY_HEADER)) && +- (reply->enumCount > 0)) ) +- { +- DbgPrint("directory_enumerate_ex: isize=%d\n", replylen); +- data = (PENUMERATE_DIRECTORY_EX_DATA)((char *)reply + sizeof(ENUMERATE_DIRECTORY_EX_REPLY)); +- isize = replylen - +- sizeof(PENUMERATE_DIRECTORY_EX_REPLY) - +- reply->enumCount * (int)(&((PENUMERATE_DIRECTORY_EX_DATA)0)->name); +- isize += (reply->enumCount * (int)(&((PENTRY_INFO)0)->name)); +- +- if (PInfo) +- { +- *PInfo = info = Novfs_Malloc(isize, GFP_KERNEL); +- if ( *PInfo ) +- { +- DbgPrint("directory_enumerate_ex1: data=0x%p info=0x%p\n", data, info); +- *Count = reply->enumCount; +- do +- { +- DbgPrint("directory_enumerate_ex2: data=0x%p length=%d\n", data); +- +- info->type = 3; +- info->mode = S_IRWXU; +- +- if (data->mode & NW_ATTRIBUTE_DIRECTORY) +- { +- info->mode |= S_IFDIR; +- info->mode |= S_IXUSR; +- } +- else +- { +- info->mode |= S_IFREG; +- } +- +- if (data->mode & NW_ATTRIBUTE_READ_ONLY) +- { +- info->mode &= ~(S_IWUSR); +- } +- +- if (data->mode & NW_ATTRIBUTE_EXECUTE) +- { +- info->mode |= S_IXUSR; +- } +- +- info->uid = current->euid; +- info->gid = current->egid; +- info->size = data->size; +- info->atime.tv_sec = data->lastAccessTime; +- info->atime.tv_nsec = 0; +- info->mtime.tv_sec = data->modifyTime; +- info->mtime.tv_nsec = 0; +- info->ctime.tv_sec = data->createTime; +- info->ctime.tv_nsec = 0; +- info->namelength = data->nameLen; +- memcpy(info->name, data->name, data->nameLen); +- data = (PENUMERATE_DIRECTORY_EX_DATA)&data->name[data->nameLen]; +- replylen = (int)((char *)&info->name[info->namelength] - (char *)info); +- DbgPrint("directory_enumerate_ex3: info=0x%p\n", info); +- mydump(replylen, info); +- +- info = (PENTRY_INFO)&info->name[info->namelength]; +- +- } while (--reply->enumCount); +- } +- } +- +- if (reply->Reply.ErrorCode) +- { +- retCode = -1; /* Eof of data */ +- } +- *EnumHandle = reply->enumerateHandle; +- } +- else +- { +- retCode = -ENODATA; +- } +- Novfs_Free(reply); +- } +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Get_Directory_List( u_char *Path, u_long *EnumHandle, PENTRY_INFO Info, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOENT; +- +- if ( -1 == *EnumHandle) +- { +- return( -ENODATA ); +- } +- +- if ( 0 == *EnumHandle ) +- { +- retCode = begin_directory_enumerate(Path, strlen(Path), EnumHandle, SessionId); +- } +- +- if ( *EnumHandle ) +- { +- retCode = directory_enumerate( EnumHandle, Info, SessionId ); +- if (retCode) +- { +- end_directory_enumerate( *EnumHandle, SessionId ); +- if ( -1 == retCode ) +- { +- retCode = 0; +- *EnumHandle = -1; +- } +- } +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Get_Directory_ListEx( u_char *Path, u_long *EnumHandle, int *Count, PENTRY_INFO *Info, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOENT; +- +- if (Count) *Count = 0; +- if (Info) *Info = NULL; +- +- if ( -1 == *EnumHandle) +- { +- return( -ENODATA ); +- } +- +- if ( 0 == *EnumHandle ) +- { +- retCode = begin_directory_enumerate(Path, strlen(Path), EnumHandle, SessionId); +- } +- +- if ( *EnumHandle ) +- { +- retCode = directory_enumerate_ex( EnumHandle, SessionId, Count, Info, INTERRUPTIBLE ); +- if (retCode) +- { +- end_directory_enumerate( *EnumHandle, SessionId ); +- if ( -1 == retCode ) +- { +- retCode = 0; +- *EnumHandle = -1; +- } +- } +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_Open_File( u_char *Path, int Flags, PENTRY_INFO Info, u_long *Handle, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- POPEN_FILE_REQUEST cmd; +- POPEN_FILE_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen, pathlen; +- +- pathlen = strlen(Path); +- +- if (StripTrailingDots) +- { +- if ('.' == Path[pathlen-1]) pathlen--; +- } +- +- cmdlen = (int)(&((POPEN_FILE_REQUEST)0)->path) + pathlen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_OPEN_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->access = 0; +- +- if ( !(Flags & O_WRONLY) || (Flags & O_RDWR)) +- { +- cmd->access |= NWD_ACCESS_READ; +- } +- +- if ((Flags & O_WRONLY) || (Flags & O_RDWR)) +- { +- cmd->access |= NWD_ACCESS_WRITE; +- } +- +- switch (Flags & (O_CREAT | O_EXCL | O_TRUNC)) +- { +- case O_CREAT: +- cmd->disp = NWD_DISP_OPEN_ALWAYS; +- break; +- +- case O_CREAT | O_EXCL: +- cmd->disp = NWD_DISP_CREATE_NEW; +- break; +- +- case O_TRUNC: +- cmd->disp = NWD_DISP_CREATE_ALWAYS; +- break; +- +- case O_CREAT | O_TRUNC: +- cmd->disp = NWD_DISP_CREATE_ALWAYS; +- break; +- +- case O_CREAT | O_EXCL | O_TRUNC: +- cmd->disp = NWD_DISP_CREATE_NEW; +- break; +- +- default: +- cmd->disp = NWD_DISP_OPEN_EXISTING; +- break; +- } +- +- cmd->mode = NWD_SHARE_READ | NWD_SHARE_WRITE | NWD_SHARE_DELETE; +- +- cmd->pathLen = pathlen; +- memcpy(cmd->path, Path, pathlen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- if( NWE_OBJECT_EXISTS == reply->Reply.ErrorCode) +- { +- retCode = -EEXIST; +- } +- else if( NWE_ACCESS_DENIED == reply->Reply.ErrorCode) +- { +- retCode = -EACCES; +- } +- else +- { +- retCode = -ENOENT; +- } +- } +- else +- { +- *Handle = reply->handle; +- retCode = 0; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Create( u_char *Path, int DirectoryFlag, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PCREATE_FILE_REQUEST cmd; +- PCREATE_FILE_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen, pathlen; +- +- pathlen = strlen(Path); +- +- if (StripTrailingDots) +- { +- if ('.' == Path[pathlen-1]) pathlen--; +- } +- +- cmdlen = (int)(&((PCREATE_FILE_REQUEST)0)->path) + pathlen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_CREATE_FILE; +- if (DirectoryFlag) +- { +- cmd->Command.CommandType = VFS_COMMAND_CREATE_DIRECOTRY; +- } +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->pathlength = pathlen; +- memcpy(cmd->path, Path, pathlen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Close_File( u_long Handle, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- CLOSE_FILE_REQUEST cmd; +- PCLOSE_FILE_REPLY reply; +- u_long replylen=0; +- int retCode; +- +- cmd.Command.CommandType = VFS_COMMAND_CLOSE_FILE; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.handle = Handle; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, 0); +- if (reply) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Read_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- READ_FILE_REQUEST cmd; +- PREAD_FILE_REPLY reply=NULL; +- u_long replylen=0; +- int retCode = 0; +- size_t len; +- +- len = *Bytes; +- *Bytes = 0; +- +- if ( ((int)(&((PREAD_FILE_REPLY)0)->data) + len) > MAX_IO_SIZE) +- { +- len = MAX_IO_SIZE - (int)(&((PREAD_FILE_REPLY)0)->data); +- len = (len/PAGE_SIZE)*PAGE_SIZE; +- } +- +- cmd.Command.CommandType = VFS_COMMAND_READ_FILE; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.handle = Handle; +- cmd.len = len; +- cmd.offset = *Offset; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- DbgPrint("Novfs_Read_File: Queue_Daemon_Command 0x%x replylen=%d\n", retCode, replylen); +- +- if (!retCode) +- { +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- else +- { +- replylen -= (int)(&((PREAD_FILE_REPLY)0)->data); +- if (replylen > 0) +- { +- if (User) +- { +- replylen -= copy_to_user(Buffer, reply->data, replylen); +- } +- else +- { +- memcpy(Buffer, reply->data, replylen); +- } +- +- *Bytes = replylen; +- } +- } +- } +- +- if ( reply ) +- { +- Novfs_Free(reply); +- } +- +- DbgPrint("Novfs_Read_File *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Write_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- WRITE_FILE_REQUEST cmd; +- PWRITE_FILE_REPLY reply=NULL; +- unsigned long replylen=0; +- int retCode=0, cmdlen; +- size_t len; +- +- unsigned long boff; +- struct page **pages; +- DATA_LIST *dlist; +- int res=0, npage, i; +- WRITE_FILE_REPLY lreply; +- +- +- len = *Bytes; +- cmdlen = (int)(&((PWRITE_FILE_REQUEST)0)->data); +- +- *Bytes = 0; +- +- memset(&lreply, 0, sizeof(lreply)); +- +- DbgPrint("Novfs_Write_File cmdlen=%ld len=%ld\n", cmdlen, len); +- +- if ( (cmdlen+len) > MAX_IO_SIZE) +- { +- len = MAX_IO_SIZE-cmdlen; +- len = (len/PAGE_SIZE)*PAGE_SIZE; +- } +- cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- cmd.handle = Handle; +- cmd.len = len; +- cmd.offset = *Offset; +- +- DbgPrint("Novfs_Write_File cmdlen=%ld len=%ld\n", cmdlen, len); +- +- npage = (((unsigned long)Buffer & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT; +- +- dlist = Novfs_Malloc(sizeof(DATA_LIST)*(npage+1), GFP_KERNEL); +- if (NULL == dlist) +- { +- return(-ENOMEM); +- } +- +- pages = Novfs_Malloc(sizeof(struct page *)*npage, GFP_KERNEL); +- +- if (NULL == pages) +- { +- Novfs_Free(dlist); +- return(-ENOMEM); +- } +- +- down_read(¤t->mm->mmap_sem); +- +- res = get_user_pages( +- current, +- current->mm, +- (unsigned long)Buffer, +- npage, +- 0, /* read type */ +- 0, /* don't force */ +- pages, +- NULL); +- +- up_read(¤t->mm->mmap_sem); +- +- DbgPrint("Novfs_Write_File res=%d\n", res); +- +- if ( res > 0 ) +- { +- boff = (unsigned long)Buffer & ~PAGE_MASK; +- +- flush_dcache_page(pages[0]); +- dlist[0].page = pages[0]; +- dlist[0].offset = (char *)boff; +- dlist[0].len = PAGE_SIZE - boff; +- dlist[0].rwflag = DLREAD; +- +- if (dlist[0].len > len) +- { +- dlist[0].len = len; +- } +- +- DbgPrint("Novfs_Write_File0: page=0x%x offset=0x%p len=%d\n", dlist[0].page, dlist[0].offset, dlist[0].len); +- +- boff = dlist[0].len; +- +- DbgPrint("Novfs_Write_File len=%d boff=%d\n", len, boff); +- +- for (i=1; (i < res) && (boff < len); i++) +- { +- flush_dcache_page(pages[i]); +- +- dlist[i].page = pages[i]; +- dlist[i].offset = NULL; +- dlist[i].len = len-boff; +- if (dlist[i].len > PAGE_SIZE) +- { +- dlist[i].len = PAGE_SIZE; +- } +- dlist[i].rwflag = DLREAD; +- +- boff += dlist[i].len; +- DbgPrint("Novfs_Write_File%d: page=0x%x offset=0x%p len=%d\n", i, dlist[i].page, dlist[i].offset, dlist[i].len); +- } +- +- dlist[i].page = NULL; +- dlist[i].offset = &lreply; +- dlist[i].len = sizeof(lreply); +- dlist[i].rwflag = DLWRITE; +- res++; +- +- DbgPrint("Novfs_Write_File Buffer=0x%x boff=0x%x len=%d\n", Buffer, boff, len); +- +- retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, res, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- } +- else +- { +- char *kdata; +- +- res = 0; +- +- kdata = Novfs_Malloc(len, GFP_KERNEL); +- if (kdata) +- { +- len -= copy_from_user(kdata, Buffer, len); +- dlist[0].page = NULL; +- dlist[0].offset = kdata; +- dlist[0].len = len; +- dlist[0].rwflag = DLREAD; +- +- dlist[1].page = NULL; +- dlist[1].offset = &lreply; +- dlist[1].len = sizeof(lreply); +- dlist[1].rwflag = DLWRITE; +- +- retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, 2, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- Novfs_Free(kdata); +- } +- } +- +- DbgPrint("Novfs_Write_File retCode=0x%x reply=0x%x\n", retCode, reply); +- +- if ( !retCode ) +- { +- switch (lreply.Reply.ErrorCode) +- { +- case 0: +- *Bytes = (size_t)lreply.bytesWritten; +- retCode = 0; +- break; +- +- case NWE_INSUFFICIENT_SPACE: +- retCode = -ENOSPC; +- break; +- +- case NWE_ACCESS_DENIED: +- retCode = -EACCES; +- break; +- +- default: +- retCode = -EIO; +- break; +- } +- } +- +- if ( res ) +- { +- for (i=0; idata); +- *Bytes = 0; +- +- if (cmdlen > MAX_IO_SIZE) +- { +- cmdlen = MAX_IO_SIZE; +- len = cmdlen - (int)(&((PWRITE_FILE_REQUEST)0)->data); +- } +- +- DbgPrint("Novfs_Write_File cmdlen=%d len=%d\n", cmdlen, len); +- +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- len -= copy_from_user(cmd->data, Buffer, len); +- DbgPrint("Novfs_Write_File len=%d\n", len); +- if (len) +- { +- cmd->Command.CommandType = VFS_COMMAND_WRITE_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->handle = Handle; +- cmd->len = len; +- cmd->offset = *Offset; +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (!retCode) +- { +- if (reply) +- { +- switch (reply->Reply.ErrorCode) +- { +- case 0: +- *Bytes = (size_t)reply->bytesWritten; +- retCode = 0; +- break; +- +- case NWE_INSUFFICIENT_SPACE: +- retCode = -ENOSPC; +- break; +- +- case NWE_ACCESS_DENIED: +- retCode = -EACCES; +- break; +- +- default: +- retCode = -EIO; +- break; +- } +- } +- } +- if ( reply ) +- { +- Novfs_Free(reply); +- } +- +- } +- Novfs_Free(cmd); +- } +- DbgPrint("Novfs_Write_File *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Read_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- READ_STREAM_REQUEST cmd; +- PREAD_STREAM_REPLY reply=NULL; +- u_long replylen=0; +- int retCode = 0; +- size_t len; +- +- len = *Bytes; +- *Bytes = 0; +- +- if ( ((int)(&((PREAD_FILE_REPLY)0)->data) + len) > MAX_IO_SIZE) +- { +- len = MAX_IO_SIZE - (int)(&((PREAD_FILE_REPLY)0)->data); +- len = (len/PAGE_SIZE)*PAGE_SIZE; +- } +- +- cmd.Command.CommandType = VFS_COMMAND_READ_STREAM; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.connection = ConnHandle; +- memcpy( cmd.handle, Handle, sizeof(cmd.handle)); +- cmd.len = len; +- cmd.offset = *Offset; +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- +- DbgPrint("Novfs_Read_Stream: Queue_Daemon_Command 0x%x replylen=%d\n", retCode, replylen); +- +- if ( reply ) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- else +- { +- replylen -= (int)(&((PREAD_STREAM_REPLY)0)->data); +- if (replylen > 0) +- { +- if (User) +- { +- replylen -= copy_to_user(Buffer, reply->data, replylen); +- } +- else +- { +- memcpy(Buffer, reply->data, replylen); +- } +- +- *Bytes = replylen; +- } +- } +- Novfs_Free(reply); +- } +- +- DbgPrint("Novfs_Read_Stream *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Write_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PWRITE_STREAM_REQUEST cmd; +- PWRITE_STREAM_REPLY reply=NULL; +- u_long replylen=0; +- int retCode=0, cmdlen; +- size_t len; +- +- len = *Bytes; +- cmdlen = len+(int)(&((PWRITE_STREAM_REQUEST)0)->data); +- *Bytes = 0; +- +- if (cmdlen > MAX_IO_SIZE) +- { +- cmdlen = MAX_IO_SIZE; +- len = cmdlen - (int)(&((PWRITE_STREAM_REQUEST)0)->data); +- } +- +- DbgPrint("Novfs_Write_Stream cmdlen=%d len=%d\n", cmdlen, len); +- +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- if (Buffer && len) +- { +- len -= copy_from_user(cmd->data, Buffer, len); +- } +- +- DbgPrint("Novfs_Write_Stream len=%d\n", len); +- +- cmd->Command.CommandType = VFS_COMMAND_WRITE_STREAM; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->connection = ConnHandle; +- memcpy(cmd->handle, Handle, sizeof(cmd->handle)); +- cmd->len = len; +- cmd->offset = *Offset; +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- switch (reply->Reply.ErrorCode) +- { +- case 0: +- retCode = 0; +- break; +- +- case NWE_INSUFFICIENT_SPACE: +- retCode = -ENOSPC; +- break; +- +- case NWE_ACCESS_DENIED: +- retCode = -EACCES; +- break; +- +- default: +- retCode = -EIO; +- break; +- } +- DbgPrint("Novfs_Write_Stream reply->bytesWritten=0x%lx\n", reply->bytesWritten); +- *Bytes = reply->bytesWritten; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- DbgPrint("Novfs_Write_Stream *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Close_Stream( u_long ConnHandle, u_char *Handle, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- CLOSE_STREAM_REQUEST cmd; +- PCLOSE_STREAM_REPLY reply; +- u_long replylen=0; +- int retCode; +- +- cmd.Command.CommandType = VFS_COMMAND_CLOSE_STREAM; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.connection = ConnHandle; +- memcpy(cmd.handle, Handle, sizeof(cmd.handle)); +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, 0); +- if (reply) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Delete( u_char *Path, int DirectoryFlag, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PDELETE_FILE_REQUEST cmd; +- PDELETE_FILE_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen, pathlen; +- +- pathlen = strlen(Path); +- +- if (StripTrailingDots) +- { +- if ('.' == Path[pathlen-1]) pathlen--; +- } +- +- cmdlen = (int)(&((PDELETE_FILE_REQUEST)0)->path) + pathlen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_DELETE_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->isDirectory = DirectoryFlag; +- cmd->pathlength = pathlen; +- memcpy(cmd->path, Path, pathlen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- if ((reply->Reply.ErrorCode & 0xFFFF) == 0x0006) /* Access Denied Error */ +- { +- retCode = -EACCES; +- } +- else +- { +- retCode = -EIO; +- } +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Truncate_File( u_char *Path, int PathLen, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PTRUNCATE_FILE_REQUEST cmd; +- PTRUNCATE_FILE_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen; +- +- if (StripTrailingDots) +- { +- if ('.' == Path[PathLen-1]) PathLen--; +- } +- cmdlen = (int)(&((PTRUNCATE_FILE_REQUEST)0)->path) + PathLen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_TRUNCATE_FILE; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- +- cmd->pathLen = PathLen; +- memcpy(cmd->path, Path, PathLen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- if (reply->Reply.ErrorCode) +- { +- retCode = -EIO; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Rename_File( int DirectoryFlag, u_char *OldName, int OldLen, u_char *NewName, int NewLen, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- RENAME_FILE_REQUEST cmd; +- PRENAME_FILE_REPLY reply; +- u_long replylen=0; +- int retCode; +- +- DbgPrint("Novfs_Rename_File:\n" \ +- " DirectoryFlag: %d\n" \ +- " OldName: %.*s\n" \ +- " NewName: %.*s\n" \ +- " SessionId: 0x%llx\n", +- DirectoryFlag, +- OldLen, OldName, +- NewLen, NewName, +- SessionId ); +- +- cmd.Command.CommandType = VFS_COMMAND_RENAME_FILE; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = SessionId; +- +- cmd.directoryFlag = DirectoryFlag; +- +- if (StripTrailingDots) +- { +- if ('.' == OldName[OldLen-1]) OldLen--; +- if ('.' == NewName[NewLen-1]) NewLen--; +- } +- +- cmd.newnameLen = NewLen; +- memcpy(cmd.newname, NewName, NewLen); +- +- cmd.oldnameLen = OldLen; +- memcpy(cmd.oldname, OldName, OldLen); +- +- retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = 0; +- if (reply->Reply.ErrorCode) +- { +- retCode = -ENOENT; +- } +- Novfs_Free(reply); +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_Set_Attr( u_char *Path, struct iattr *Attr, session_t SessionId ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSET_FILE_INFO_REQUEST cmd; +- PSET_FILE_INFO_REPLY reply; +- u_long replylen=0; +- int retCode, cmdlen, pathlen; +- +- pathlen = strlen(Path); +- +- if (StripTrailingDots) +- { +- if ('.' == Path[pathlen-1]) pathlen--; +- } +- +- cmdlen = (int)(&((PSET_FILE_INFO_REQUEST)0)->path) + pathlen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_SET_FILE_INFO; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = SessionId; +- cmd->fileInfo.ia_valid = Attr->ia_valid; +- cmd->fileInfo.ia_mode = Attr->ia_mode; +- cmd->fileInfo.ia_uid = Attr->ia_uid; +- cmd->fileInfo.ia_gid = Attr->ia_uid; +- cmd->fileInfo.ia_size = Attr->ia_size; +- cmd->fileInfo.ia_atime = Attr->ia_atime.tv_sec; +- cmd->fileInfo.ia_mtime = Attr->ia_mtime.tv_sec;; +- cmd->fileInfo.ia_ctime = Attr->ia_ctime.tv_sec;; +-/* +- cmd->fileInfo.ia_attr_flags = Attr->ia_attr_flags; +-*/ +- cmd->fileInfo.ia_attr_flags = 0; +- +- cmd->pathlength = pathlen; +- memcpy(cmd->path, Path, pathlen); +- +- retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- switch( reply->Reply.ErrorCode ) +- { +- case 0: +- retCode = 0; +- break; +- +- case NWE_PARAM_INVALID: +- retCode = -EINVAL; +- break; +- +- default: +- retCode = -EIO; +- break; +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- else +- { +- retCode = -ENOMEM; +- } +- return( retCode ); +-} +diff -uNr src.old/novfs/inode.c src/novfs/inode.c +--- src.old/novfs/inode.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,4584 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: inode.c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module contains functions used to control +- * access to the Linux file system. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/*===[ Include files specific to this module ]============================*/ +-#include "vfs.h" +- +-/*===[ External data ]====================================================*/ +- +-/*===[ External prototypes ]==============================================*/ +-extern int DbgPrint( char *Fmt, ... ); +-extern int LocalPrint( char *Fmt, ... ); +- +-extern int Init_Procfs_Interface( void ); +-extern void Uninit_Procfs_Interface( void ); +-extern void mydump(int size, void *dumpptr); +- +-/* +- * Daemon.c functions +- */ +-extern void Init_Daemon_Queue( void ); +-extern void Uninit_Daemon_Queue( void ); +-extern int do_logout( struct qstr *Server ); +-extern int Daemon_SetMountPoint( char *Path ); +- +-/* +- * file.c functions +- */ +-extern int Novfs_verify_file( struct qstr *Path, session_t SessionId ); +-extern int Novfs_get_alltrees(struct dentry *parent); +-extern int Novfs_Get_Connected_Server_List( unsigned char **ServerList, session_t SessionId ); +-extern int Novfs_Get_Server_Volume_List( struct qstr *Server, unsigned char **VolumeList, session_t SessionId ); +-extern int Novfs_Verify_Server_Name( struct qstr *Server, session_t SessionId ); +-extern int Novfs_Verify_Volume_Name( struct qstr *Server, struct qstr *Volume, session_t SessionId ); +-extern int Novfs_Get_File_Info( unsigned char *Path, PENTRY_INFO Info, session_t SessionId ); +-extern int Novfs_Get_Directory_List( unsigned char *Path, unsigned long *EnumHandle, PENTRY_INFO Info, session_t SessionId ); +-extern int Novfs_Get_Directory_ListEx( unsigned char *Path, unsigned long *EnumHandle, int *Count, PENTRY_INFO *Info, session_t SessionId ); +-extern int Novfs_Open_File( unsigned char *Path, int Flags, PENTRY_INFO Info, unsigned long *Handle, session_t SessionId ); +-extern int Novfs_Create( unsigned char *Path, int DirectoryFlag, session_t SessionId ); +-extern int Novfs_Close_File( unsigned long Handle, session_t SessionId ); +-extern int Novfs_Read_File( unsigned long Handle, unsigned char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId); +-extern int Novfs_Write_File( unsigned long Handle, unsigned char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); +-extern int Novfs_Delete( unsigned char *Path, int DirectoryFlag, session_t SessionId ); +-extern int Novfs_Truncate_File( unsigned char *Path, int PathLen, session_t SessionId ); +-extern int Novfs_Rename_File( int DirectoryFlag, unsigned char *OldName, int OldLen, unsigned char *NewName, int NewLen, session_t SessionId ); +-extern int Novfs_Set_Attr( unsigned char *Path, struct iattr *Attr, session_t SessionId ); +- +-/* +- * scope.c functions +- */ +-extern void Scope_Init( void ); +-extern void Scope_Uninit( void ); +-extern void *Scope_Lookup( void ); +-extern unsigned long Scope_Get_Hash( void *); +-extern uid_t Scope_Get_Uid( void *); +-extern session_t Scope_Get_SessionId( void *Scope ); +-extern void *Scope_Get_ScopefromName( struct qstr *Name ); +-extern void *Scope_Get_ScopefromPath( struct dentry *Dentry ); +-extern char *Scope_Get_ScopeUsers( void ); +-extern int Scope_Set_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); +-extern int Scope_Get_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); +-extern char *Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags); +- +-/* +- * profile.c functions +- */ +-extern int init_profile( void ); +- +-/*===[ Manifest constants ]===============================================*/ +-#define FILE_UPDATE_TIMEOUT 2 +- +-/*===[ Type definitions ]=================================================*/ +- +-/*===[ Function prototypes ]==============================================*/ +-int Novfs_Remove_from_Root(char *RemoveName); +-int Novfs_Add_to_Root(char *); +-char *Novfs_dget_path( struct dentry *d, char *path, unsigned int pathlen ); +-int verify_dentry(struct dentry *dentry, int Flags); +-int invalidate_dentry(struct dentry *parent); +-struct dentry *Novfs_d_lookup(struct dentry *Parent, struct qstr *Name); +-int Novfs_d_add(struct dentry *p, struct dentry *d, struct inode *i, int add); +-int Novfs_d_strcmp (struct qstr *s1, struct qstr *s2); +-struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t uid, ino_t ino, struct qstr *name); +-unsigned long Novfs_internal_hash (struct qstr *name); +- +-struct super_block *Novfs_get_sb (struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data); +-void Novfs_kill_sb(struct super_block *SB); +-int Novfs_fill_super (struct super_block *SB, void *Data, int Silent); +- +-/* +- * Declared dentry_operations +- */ +-int Novfs_d_revalidate(struct dentry *, struct nameidata *); +-int Novfs_d_hash (struct dentry *, struct qstr *); +-int Novfs_d_compare (struct dentry *, struct qstr *, struct qstr *); +-int Novfs_d_delete(struct dentry *dentry); +-void Novfs_d_release(struct dentry *dentry); +-void Novfs_d_iput(struct dentry *dentry, struct inode *inode); +- +-/* +- * Declared directory operations +- */ +-int Novfs_dir_open(struct inode *inode, struct file *file); +-int Novfs_dir_release(struct inode *inode, struct file *file); +-loff_t Novfs_dir_lseek(struct file *file, loff_t offset, int origin); +-int Novfs_dir_read(struct file *file, char *buf, size_t len, loff_t *off); +-void addtodentry( struct dentry *Parent, unsigned char *List, int Level ); +-int Novfs_filldir(void *data, const char *name, int namelen, loff_t off, ino_t ino, unsigned ftype); +-int Novfs_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); +-int Novfs_dir_fsync(struct file * file, struct dentry *dentry, int datasync); +- +-/* +- * Declared address space operations +- */ +-int Novfs_a_readpage(struct file *file, struct page *page); +- +-/* +- * Declared file_operations +- */ +-ssize_t Novfs_f_read(struct file *, char *, size_t, loff_t *); +-ssize_t Novfs_f_write(struct file *, const char *, size_t, loff_t *); +-int Novfs_f_readdir(struct file *, void *, filldir_t); +-int Novfs_f_ioctl(struct inode *, struct file *, unsigned int, unsigned long); +-int Novfs_f_mmap(struct file * file, struct vm_area_struct * vma); +-int Novfs_f_open(struct inode *, struct file *); +-int Novfs_f_flush(struct file *); +-int Novfs_f_release(struct inode *, struct file *); +-int Novfs_f_fsync(struct file *, struct dentry *, int datasync); +-int Novfs_f_lock(struct file *, int, struct file_lock *); +- +-/* +- * Declared inode_operations +- */ +-int Novfs_i_create(struct inode *,struct dentry *,int, struct nameidata *); +-struct dentry * Novfs_i_lookup(struct inode *,struct dentry *, struct nameidata *); +-int Novfs_i_mkdir(struct inode *,struct dentry *,int); +-int Novfs_i_unlink(struct inode *dir, struct dentry *dentry); +-int Novfs_i_rmdir(struct inode *,struct dentry *); +-int Novfs_i_mknod(struct inode *,struct dentry *,int,dev_t); +-int Novfs_i_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +-int Novfs_i_permission(struct inode *inode, int mask); +-int Novfs_i_setattr(struct dentry *, struct iattr *); +-int Novfs_i_getattr(struct vfsmount *mnt, struct dentry *, struct kstat *); +-int Novfs_i_revalidate(struct dentry *dentry); +- +-void update_inode(struct inode *Inode, PENTRY_INFO Info); +- +-/* +- * Declared super_operations +- */ +-void Novfs_read_inode(struct inode *inode); +-void Novfs_write_inode(struct inode *inode); +-int Novfs_notify_change(struct dentry *dentry, struct iattr *attr); +-void Novfs_clear_inode(struct inode *inode); +-int Novfs_show_options( struct seq_file *s, struct vfsmount *m ); +-int Novfs_statfs(struct super_block *sb, struct kstatfs *buf); +- +-/* +- * Declared control interface functions +- */ +-ssize_t +-Novfs_Control_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos); +- +-ssize_t +-Novfs_Control_write(struct file * file, const char * buf, size_t nbytes, loff_t *ppos); +- +-int Novfs_Control_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +- +-int __init init_novfs(void); +-void __exit exit_novfs(void); +- +-int Novfs_lock_inode_cache( struct inode *i ); +-void Novfs_unlock_inode_cache( struct inode *i ); +-int Novfs_enumerate_inode_cache( struct inode *i, struct list_head **iteration, ino_t *ino, PENTRY_INFO info); +-int Novfs_get_entry( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info); +-int Novfs_get_entry_time( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info, u64 *EntryTime); +-int Novfs_get_remove_entry( struct inode *i, ino_t *ino, PENTRY_INFO info); +-void Novfs_invalidate_inode_cache( struct inode *i ); +-PDIR_CACHE Novfs_lookup_inode_cache( struct inode *i, struct qstr *name, ino_t ino ); +-int Novfs_lookup_validate( struct inode *i, struct qstr *name, ino_t ino ); +-int Novfs_add_inode_entry( struct inode *i, struct qstr *name, ino_t ino, PENTRY_INFO info); +-int Novfs_update_entry( struct inode *i, struct qstr *name, ino_t ino, PENTRY_INFO info); +-void Novfs_remove_inode_entry( struct inode *i, struct qstr *name, ino_t ino); +-void Novfs_free_invalid_entries( struct inode *i ); +-void Novfs_free_inode_cache( struct inode *i ); +- +-/*===[ Global variables ]=================================================*/ +-struct dentry_operations Novfs_dentry_operations = { +- .d_revalidate = Novfs_d_revalidate, +- .d_hash = Novfs_d_hash, +- .d_compare = Novfs_d_compare, +- .d_delete = Novfs_d_delete, +- .d_release = Novfs_d_release, +- .d_iput = Novfs_d_iput, +-}; +- +-struct file_operations Novfs_dir_operations = { +- .open = Novfs_dir_open, +- .release = Novfs_dir_release, +- .llseek = Novfs_dir_lseek, +- .read = Novfs_dir_read, +- .readdir = Novfs_dir_readdir, +- .fsync = Novfs_dir_fsync, +-}; +- +-static struct file_operations Novfs_file_operations = { +- .read = Novfs_f_read, +- .write = Novfs_f_write, +- .readdir = Novfs_f_readdir, +- .ioctl = Novfs_f_ioctl, +- .mmap = Novfs_f_mmap, +- .open = Novfs_f_open, +- .release = Novfs_f_release, +- .fsync = Novfs_f_fsync, +- .llseek = generic_file_llseek, +-}; +- +-static struct address_space_operations Novfs_aops = { +- .readpage = Novfs_a_readpage, +-}; +- +-static struct inode_operations Novfs_inode_operations = { +- .create = Novfs_i_create, +- .lookup = Novfs_i_lookup, +- .unlink = Novfs_i_unlink, +- .mkdir = Novfs_i_mkdir, +- .rmdir = Novfs_i_rmdir, +- .mknod = Novfs_i_mknod, +- .rename = Novfs_i_rename, +- .setattr = Novfs_i_setattr, +- .getattr = Novfs_i_getattr, +-}; +- +-static struct inode_operations Novfs_file_inode_operations = { +- .setattr = Novfs_i_setattr, +- .getattr = Novfs_i_getattr, +-}; +- +-static struct super_operations Novfs_ops = { +- .read_inode = Novfs_read_inode, +- .statfs = Novfs_statfs, +- .clear_inode = Novfs_clear_inode, +- .drop_inode = generic_delete_inode, +- .show_options = Novfs_show_options, +- +-}; +- +-/* Not currently used +-static struct file_operations Novfs_Control_operations = { +- .read = Novfs_Control_read, +- .write = Novfs_Control_write, +- .ioctl = Novfs_Control_ioctl, +-}; +-*/ +- +-ino_t Novfs_Inode_Number=1; +- +-static struct file_system_type Novfs_fs_type = { +- .name = "novfs", +- .get_sb = Novfs_get_sb, +- .kill_sb = Novfs_kill_sb, +- .owner = THIS_MODULE, +-}; +- +-struct dentry *Novfs_root=NULL; +- +-int Novfs_Version_Major=NOVFS_VFS_MAJOR; +-int Novfs_Version_Minor=NOVFS_VFS_MINOR; +-int Novfs_Version_Sub=NOVFS_VFS_SUB; +-int Novfs_Version_Release=NOVFS_VFS_RELEASE; +- +-char *Novfs_CurrentMount=NULL; +- +-DECLARE_MUTEX(InodeList_lock); +- +-LIST_HEAD(InodeList); +- +-unsigned long InodeCount=0, DCCount=0; +-unsigned long File_update_timeout=FILE_UPDATE_TIMEOUT; +-/*===[ Code ]=============================================================*/ +-static __inline__ void PRINT_DENTRY(const char *s, struct dentry *d) +-{ +- DbgPrint("%s: 0x%x\n", s, d); +- DbgPrint(" d_count: 0x%x\n", d->d_count); +- DbgPrint(" d_lock: 0x%x\n", d->d_lock); +- DbgPrint(" d_inode: 0x%x\n", d->d_inode); +- DbgPrint(" d_lru: 0x%x\n" \ +- " next: 0x%x\n" \ +- " prev: 0x%x\n", &d->d_lru, d->d_lru.next, d->d_lru.prev); +- DbgPrint(" d_child: 0x%x\n" \ +- " next: 0x%x\n" \ +- " prev: 0x%x\n", &d->D_CHILD, d->D_CHILD.next, d->D_CHILD.prev); +- DbgPrint(" d_subdirs: 0x%x\n" \ +- " next: 0x%x\n" \ +- " prev: 0x%x\n", &d->d_subdirs, d->d_subdirs.next, d->d_subdirs.prev); +- DbgPrint(" d_alias: 0x%x\n" \ +- " next: 0x%x\n" \ +- " prev: 0x%x\n", &d->d_alias, d->d_alias.next, d->d_alias.prev); +- DbgPrint(" d_time: 0x%x\n", d->d_time); +- DbgPrint(" d_op: 0x%x\n", d->d_op); +- DbgPrint(" d_sb: 0x%x\n", d->d_sb); +- DbgPrint(" d_flags: 0x%x\n", d->d_flags); +- DbgPrint(" d_mounted: 0x%x\n", d->d_mounted); +- DbgPrint(" d_fsdata: 0x%x\n", d->d_fsdata); +-/* DbgPrint(" d_cookie: 0x%x\n", d->d_cookie); */ +- DbgPrint(" d_parent: 0x%x\n", d->d_parent); +- DbgPrint(" d_name: 0x%x %.*s\n", &d->d_name, d->d_name.len, d->d_name.name); +- DbgPrint(" name: 0x%x\n" \ +- " len: %d\n" \ +- " hash: 0x%x\n", d->d_name.name, d->d_name.len, d->d_name.hash); +- DbgPrint(" d_hash: 0x%x\n" \ +- " next: 0x%x\n" \ +- " pprev: 0x%x\n", d->d_hash, d->d_hash.next, d->d_hash.pprev); +-} +- +-/*++======================================================================*/ +-int Novfs_Remove_from_Root(char *RemoveName) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct qstr name; +- struct dentry *dentry; +- struct inode *dir; +- +- DbgPrint( "Novfs_Remove_from_Root: %s\n", RemoveName); +- name.len = strlen(RemoveName); +- name.name = RemoveName; +- Novfs_d_hash(Novfs_root, &name); +- +- dentry = d_lookup( Novfs_root, &name); +- if (dentry) +- { +- if (dentry->d_inode && dentry->d_inode->u.generic_ip) +- { +- ((PINODE_DATA)(dentry->d_inode->u.generic_ip))->Scope = NULL; +- } +- dput(dentry); +- } +- +- +- dir = Novfs_root->d_inode; +- +- Novfs_lock_inode_cache( dir ); +- Novfs_remove_inode_entry( dir, &name, 0); +- Novfs_unlock_inode_cache( dir ); +- +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_Add_to_Root(char *AddName) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct qstr name; +- struct inode *dir; +- ENTRY_INFO info; +- ino_t ino; +- +- DbgPrint( "Novfs_Add_to_Root: %s\n", AddName); +- name.len = strlen(AddName); +- name.name = AddName; +- Novfs_d_hash(Novfs_root, &name); +- +- dir = Novfs_root->d_inode; +- +- Novfs_lock_inode_cache( dir ); +- +- ino = 0; +- +- if ( !Novfs_lookup_inode_cache(dir, &name, 0)) +- { +- info.mode = S_IFDIR | 0700; +- info.size = 0; +- info.atime = info.ctime = info.mtime = CURRENT_TIME; +- +- ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); +- Novfs_add_inode_entry( dir, &name, ino, &info); +- } +- +- Novfs_unlock_inode_cache( dir ); +- +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_Add_to_Root2(char *AddName) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct dentry *entry; +- struct qstr name; +- struct inode *inode; +- void *scope; +- +- DbgPrint( "Novfs_Add_to_Root: %s\n", AddName); +- name.len = strlen(AddName); +- name.name = AddName; +- +- Novfs_d_hash(Novfs_root, &name); +- +- entry = Novfs_d_lookup(Novfs_root, &name); +- DbgPrint( "Novfs_Add_to_Root: Novfs_d_lookup 0x%x\n", entry); +- if ( NULL == entry ) +- { +- scope = Scope_Lookup(); +- +- entry = d_alloc(Novfs_root, &name); +- DbgPrint( "Novfs_Add_to_Root: d_alloc 0x%x\n", entry ); +- if (entry) +- { +- entry->d_op = &Novfs_dentry_operations; +- entry->d_time = jiffies+(File_update_timeout*HZ); +- /* +- * done in Novfs_d_add now... entry->d_fsdata = (void *)Novfs_internal_hash( &name ); +- */ +- inode = Novfs_get_inode(Novfs_root->d_sb, S_IFDIR | 0700, 0, Scope_Get_Uid(scope), 0, &name); +- DbgPrint( "Novfs_Add_to_Root: Inode=0x%x\n", inode); +- if (inode) +- { +- inode->i_atime = +- inode->i_ctime = +- inode->i_mtime = CURRENT_TIME; +- if ( !Novfs_d_add(Novfs_root, entry, inode, 1)) +- { +- if (inode->u.generic_ip) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Flags = USER_INODE; +- } +- PRINT_DENTRY("After Novfs_d_add", entry); +- } +- else +- { +- dput(entry); +- iput(inode); +- } +- } +- } +- } +- else +- { +- dput(entry); +- PRINT_DENTRY("Novfs_Add_to_Root: After dput Dentry", entry); +- } +- return(0); +-} +- +-/*++======================================================================*/ +-char *Novfs_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen) +-/* +- * Arguments: struct dentry *Dentry - starting entry +- * char *Buf - pointer to memory buffer +- * unsigned int Buflen - size of memory buffer +- * +- * Returns: pointer to path. +- * +- * Abstract: Walks the dentry chain building a path. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *retval=&Buf[Buflen]; +- struct dentry *p=Dentry; +- +- *(--retval) = '\0'; +- Buflen--; +- +- if (!IS_ROOT(p) && !IS_ROOT(p->d_parent)) +- { +- while (Buflen && !IS_ROOT(p) && !IS_ROOT(p->d_parent)) +- { +- if (Buflen > p->d_name.len) +- { +- retval -= p->d_name.len; +- Buflen -= p->d_name.len; +- memcpy(retval, p->d_name.name, p->d_name.len); +- *(--retval) = '\\'; +- Buflen--; +- p = p->d_parent; +- } +- else +- { +- retval = NULL; +- break; +- } +- } +- } +- else +- { +- *(--retval) = '\\'; +- } +- +- +- +-if (retval) DbgPrint("Novfs_dget_path: %s\n", retval); +- return(retval); +-} +- +-/*++======================================================================*/ +-int verify_dentry( struct dentry *dentry, int Flags ) +-/* +- * Arguments: struct dentry *dentry - entry to verify +- * +- * Returns: zero - Inode cache has been updated. If not in the cache +- * then file doesn't exist. +- * !zero - Error +- * +- * Abstract: This routine will verify if the file that dentry is pointing +- * at exist and if it does it will put it in the inode cache of +- * the parent. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal = -ENOENT; +- struct inode *dir; +- PENTRY_INFO info=NULL; +- PINODE_DATA id; +- session_t session; +- char *path, *list=NULL, *cp; +- ino_t ino; +- struct qstr name; +- int iLock=0; +- struct dentry *parent=NULL; +- u64 ctime; +- struct inode *inode; +- +- if ( IS_ROOT(dentry) ) +- { +- DbgPrint("verify_dentry: Root entry\n"); +- return( 0 ); +- } +- +- if ( dentry && dentry->d_parent && +- (dir = dentry->d_parent->d_inode) && +- (id = dir->u.generic_ip) ) +- { +- parent = dget_parent(dentry); +- +- info = Novfs_Malloc(sizeof(ENTRY_INFO)+PATH_LENGTH_BUFFER, GFP_KERNEL); +- +- if (info) +- { +- if (Novfs_lock_inode_cache( dir )) +- { +- name.len = dentry->d_name.len; +- name.name = dentry->d_name.name; +- name.hash = Novfs_internal_hash( &name ); +- if ( !Novfs_get_entry_time(dir, &name, &ino, info, &ctime)) +- { +- inode = dentry->d_inode; +- if ( inode && +- ( (inode->i_size != info->size) || +- (inode->i_mtime.tv_sec != info->mtime.tv_sec) )) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; +- } +- +- ctime = get_jiffies_64() - ctime; +- if ( Flags || ctime < (u64)(File_update_timeout*HZ) ) +- { +- retVal = 0; +- Novfs_unlock_inode_cache(dir); +- dput(parent); +- Novfs_Free(info); +- return(0); +- } +- } +- Novfs_unlock_inode_cache(dir); +- } +- +- if ( IS_ROOT(dentry->d_parent) ) +- { +- session = Scope_Get_SessionId(Scope_Get_ScopefromName(&dentry->d_name)); +- } +- else +- { +- session = Scope_Get_SessionId( id->Scope ); +- } +- +- if ( !session ) +- { +- id->Scope = Scope_Get_ScopefromPath(dentry); +- session = Scope_Get_SessionId( id->Scope ); +- } +- +- ino = 0; +- retVal = 0; +- +- if ( IS_ROOT(dentry->d_parent) ) +- { +- DbgPrint("verify_dentry: parent is Root directory\n"); +- list = Scope_Get_ScopeUsers(); +- +- iLock = Novfs_lock_inode_cache( dir ); +- Novfs_invalidate_inode_cache( dir ); +- +- if ( list ) +- { +- cp = list; +- while (*cp) +- { +- name.name = cp; +- name.len = strlen(cp); +- name.hash = Novfs_internal_hash( &name ); +- cp += (name.len+1); +- ino = 0; +- if ( Novfs_get_entry( dir, &name, &ino, info ) ) +- { +- info->mode = S_IFDIR | 0700; +- info->size = 0; +- info->atime = info->ctime = info->mtime = CURRENT_TIME; +- ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); +- Novfs_add_inode_entry(dir, &name, ino, info); +- } +- } +- } +- Novfs_free_invalid_entries( dir ); +- } +- else +- { +- +- path = Novfs_dget_path(dentry, info->name, PATH_LENGTH_BUFFER); +- if (path) +- { +- if (dentry->d_name.len <= NW_MAX_PATH_LENGTH) +- { +- name.hash = Novfs_internal_hash(&dentry->d_name); +- name.len = dentry->d_name.len; +- name.name = dentry->d_name.name; +- +- +- +- retVal = Novfs_Get_File_Info( path, info, session ); +- if ( 0 == retVal) +- { +- dentry->d_time = jiffies+(File_update_timeout*HZ); +- iLock = Novfs_lock_inode_cache( dir ); +- if ( Novfs_update_entry( dir, &name, 0, info ) ) +- { +- if (dentry->d_inode) +- { +- ino = dentry->d_inode->i_ino; +- } +- else +- { +- ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); +- } +- Novfs_add_inode_entry( dir, &name, ino, info); +- } +- if ( dentry->d_inode ) +- { +- update_inode(dentry->d_inode, info); +- id->Flags &= ~UPDATE_INODE; +- +- dentry->d_inode->i_flags &= ~S_DEAD; +- if (dentry->d_inode->u.generic_ip) +- { +- ((PINODE_DATA)dentry->d_inode->u.generic_ip)->Scope = id->Scope; +- } +- } +- } +- else if (-EINTR != retVal) +- { +- retVal = 0; +- iLock = Novfs_lock_inode_cache( dir ); +- Novfs_remove_inode_entry( dir, &name, 0 ); +- if ( dentry->d_inode && !(dentry->d_inode->i_flags & S_DEAD) ) +- { +- dentry->d_inode->i_flags |= S_DEAD; +- dentry->d_inode->i_size = 0; +- dentry->d_inode->i_atime.tv_sec = +- dentry->d_inode->i_atime.tv_nsec = +- dentry->d_inode->i_ctime.tv_sec = +- dentry->d_inode->i_ctime.tv_nsec = +- dentry->d_inode->i_mtime.tv_sec = +- dentry->d_inode->i_mtime.tv_nsec = 0; +- dentry->d_inode->i_blocks = 0; +- d_delete(dentry); /* Remove from cache */ +- } +- } +- } +- else +- { +- retVal = -ENAMETOOLONG; +- } +- } +- } +- } +- else +- { +- retVal = -ENOMEM; +- } +- if (iLock) +- { +- Novfs_unlock_inode_cache( dir ); +- } +- dput(parent); +- } +- +- if (list) Novfs_Free(list); +- if (info) Novfs_Free(info); +- +- DbgPrint("verify_dentry: return=0x%x\n", retVal); +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-struct dentry *Novfs_d_lookup(struct dentry *Parent, struct qstr *Name) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- return( d_lookup( Parent, Name)); +-} +- +-/*++======================================================================*/ +-int Novfs_d_add(struct dentry *Parent, struct dentry *d, struct inode *i, int a) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- void *scope; +- PINODE_DATA id=NULL; +- +- char *path, *buf; +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(d, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- DbgPrint("Novfs_d_add: inode=0x%p ino=%d path %s\n", i, i->i_ino, path); +- } +- Novfs_Free(buf); +- } +- +- if ( Parent && Parent->d_inode && Parent->d_inode->u.generic_ip) +- { +- id = (PINODE_DATA)Parent->d_inode->u.generic_ip; +- } +- +- if (id && id->Scope) +- { +- scope = id->Scope; +- } +- else +- { +- scope = Scope_Get_ScopefromPath( d ); +- } +- +- ((PINODE_DATA)i->u.generic_ip)->Scope = scope; +- +- d->d_time = jiffies+(File_update_timeout*HZ); +- if (a) +- { +- d_add(d, i); +- } +- else +- { +- d_instantiate(d, i); +- } +- +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) +-/* +- * Arguments: struct dentry *dentry - pointer to dentry to revalidate. +- * struct nameidata *nd - pointer to nameidata. +- * +- * Returns: zero - dentry is not valid. +- * !zero - valid entry +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = 0; +- struct inode *dir; +- PINODE_DATA id; +- struct qstr name; +- +- UNUSED_VARIABLE( nd ); +- +- DbgPrint("Novfs_d_revalidate: 0x%p %.*s\n" \ +- " d_count: %d\n" \ +- " d_inode: 0x%p\n", +- dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_count, dentry->d_inode); +- +- if (IS_ROOT( dentry )) +- { +- retCode = 1; +- } +- else +- { +- if ( dentry->d_inode && +- dentry->d_parent && +- (dir = dentry->d_parent->d_inode) && +- (id = dir->u.generic_ip) ) +- { +- /* +- * Check timer to see if in valid time limit +- */ +- if (jiffies > dentry->d_time) +- { +- /* +- * Revalidate entry +- */ +- name.len = dentry->d_name.len; +- name.name = dentry->d_name.name; +- name.hash = Novfs_internal_hash(&dentry->d_name); +- dentry->d_time = 0; +- +- if ( 0 == verify_dentry( dentry, 0 )) +- { +- if (Novfs_lock_inode_cache( dir )) +- { +- if (Novfs_lookup_inode_cache( dir, &name, 0)) +- { +- dentry->d_time = jiffies + (File_update_timeout*HZ); +- retCode = 1; +- } +- Novfs_unlock_inode_cache( dir ); +- } +- } +- } +- else +- { +- retCode = 1; +- } +- } +- } +- +- +- if ( ( 0 == retCode ) && dentry->d_inode ) +- { +- /* +- * Entry has become invalid +- */ +-/* dput(dentry); +-*/ +- } +- +- DbgPrint("Novfs_d_revalidate: return 0x%x\n", retCode); +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-unsigned long Novfs_internal_hash (struct qstr *name) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- unsigned long hash = 0; +- unsigned int len = name->len; +- unsigned char *c = (unsigned char *)name->name; +- +- while(len--) +- { +- /* +- * Lower case values for the hash. +- */ +- hash = partial_name_hash(tolower(*c++), hash); +- } +- +- return(hash); +-} +- +-/*++======================================================================*/ +-int Novfs_d_hash (struct dentry *dentry, struct qstr *name) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- UNUSED_VARIABLE( dentry ); +- +- DbgPrint("Novfs_d_hash: %.*s\n", name->len, name->name); +- +- name->hash = Novfs_internal_hash( name ); +- +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_d_strcmp (struct qstr *s1, struct qstr *s2) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = 1; +- unsigned char *str1, *str2; +- unsigned int len; +- +- DbgPrint("Novfs_d_strcmp: s1=%.*s s2=%.*s\n", s1->len, s1->name, s2->len, s2->name); +- +- if (s1->len && (s1->len == s2->len) && (s1->hash == s2->hash) ) +- { +- len = s1->len; +- str1 = (unsigned char *)s1->name; +- str2 = (unsigned char *)s2->name; +- for ( retCode = 0; len-- ; str1++, str2++ ) +- { +- if (*str1 != *str2) +- { +- if (tolower(*str1) != tolower(*str2)) +- { +- retCode = 1; +- break; +- } +- } +- } +- } +- +- DbgPrint("Novfs_d_strcmp: retCode=0x%x\n", retCode); +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_d_compare (struct dentry *parent, struct qstr *s1, struct qstr *s2) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode; +- +- retCode = Novfs_d_strcmp(s1, s2); +- +- DbgPrint("Novfs_d_compare: retCode=0x%x\n", retCode); +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_d_delete(struct dentry *dentry) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retVal = 0; +- +- DbgPrint("Novfs_d_delete: 0x%p %.*s\n" \ +- " d_count: %d\n" \ +- " d_inode: 0x%p\n", +- dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_count, dentry->d_inode); +- +- if (dentry->d_inode && (dentry->d_inode->i_flags & S_DEAD)) +- { +- retVal = 1; +- } +- +- dentry->d_time = 0; +- +- return( retVal ); +-} +- +-/*++======================================================================*/ +-void Novfs_d_release(struct dentry *dentry) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DbgPrint("Novfs_d_release: 0x%x %.*s\n", dentry, dentry->d_name.len, dentry->d_name.name); +-} +- +-/*++======================================================================*/ +-void Novfs_d_iput(struct dentry *dentry, struct inode *inode) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DbgPrint("Novfs_d_iput: Inode=0x%x Ino=%d Dentry=0x%x Name=%.*s\n", +- inode, inode->i_ino, dentry, dentry->d_name.len, dentry->d_name.name); +- +- iput(inode); +- +-} +-/*++======================================================================*/ +-int Novfs_dir_open(struct inode *dir, struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *path, *buf; +- +- +- DbgPrint("Novfs_dir_open: Inode 0x%x %d Name %.*s\n", dir, dir->i_ino, file->f_dentry->d_name.len, file->f_dentry->d_name.name); +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- DbgPrint("Novfs_dir_open: path %s\n", path); +- } +- Novfs_Free(buf); +- } +- file->private_data = NULL; +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_dir_release(struct inode *dir, struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct inode *inode; +- +- DbgPrint("Novfs_dir_release: Inode 0x%x %d Name %.*s\n", dir, dir->i_ino, file->f_dentry->d_name.len, file->f_dentry->d_name.name); +- if (file->private_data) +- { +- inode = file->private_data; +- Novfs_free_inode_cache( inode ); +- Novfs_Free(file->private_data); +- } +- +- return(0); +-} +- +-/*++======================================================================*/ +-loff_t Novfs_dir_lseek(struct file *file, loff_t offset, int origin) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- return(dcache_dir_lseek(file, offset, origin)); +-} +- +-/*++======================================================================*/ +-int Novfs_dir_read(struct file *file, char *buf, size_t len, loff_t *off) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-/* +- int rlen = 0; +- +- DbgPrint("Novfs_dir_readdir: dentry path %.*s buf=0x%p len=%d off=%lld\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, buf, len, *off); +- +- if (0 == *off) +- { +- rlen = 8; +- rlen -= copy_to_user(buf, "Testing\n", 8); +- *off += rlen; +- } +- return(rlen); +-*/ +- return(generic_read_dir(file, buf, len, off)); +-} +- +-/*++======================================================================*/ +-void process_list(struct file *File, char *List, int Type, PENTRY_INFO Info, session_t SessionId) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- unsigned char *path, *buf=NULL, *cp; +- struct inode *dir = File->f_dentry->d_inode; +- struct qstr name; +- ino_t ino=0; +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- path = buf; +- if (buf) +- { +- path = Novfs_dget_path(File->f_dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- strcpy(buf, path); +- } +- path = buf+strlen(buf); +- *path++ = '\\'; +- } +- +- if ( List ) +- { +- cp = List; +- while (*cp) +- { +- name.name = cp; +- name.len = strlen(cp); +- name.hash = Novfs_internal_hash( &name ); +- cp += (name.len+1); +- +- Info->mode = S_IFDIR | 0700; +- Info->size = 0; +- Info->atime = Info->ctime = Info->mtime = CURRENT_TIME; +- +- if ( (USER_LIST != Type) && buf && ((int)(path-buf)+name.len < PATH_LENGTH_BUFFER) ) +- { +- strcpy(path, name.name); +- Novfs_Get_File_Info(buf, Info, SessionId); +- } +- +- if ( Novfs_update_entry( dir, &name, ino, Info ) ) +- { +- Novfs_add_inode_entry(dir, &name, (ino_t)InterlockedIncrement(&Novfs_Inode_Number), Info); +- } +- } +- } +- +- if (buf) Novfs_Free(buf); +- +-} +- +-/*++======================================================================*/ +-int Novfs_dir_readdir(struct file * file, void * dirent, filldir_t filldir) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- unsigned char *path, *buf=NULL; +- unsigned char *list=NULL; +- PENTRY_INFO info=NULL, pinfo, iinfo; +- int count; +- +- int status = -ENOMEM; +- struct inode *inode; +- session_t sessionId; +- uid_t uid; +- struct qstr name; +- struct list_head *inter; +- ino_t ino; +- int iLock=0; +- int type = 0; +- +- DbgPrint("Novfs_dir_readdir(%s): dentry path %.*s 0x%x\n", current->comm, file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_dentry->d_fsdata); +- +- inode = file->f_dentry->d_inode; +- +- info = Novfs_Malloc(sizeof(ENTRY_INFO)+PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (info) +- { +- if (file->f_pos) +- { +- if (file->private_data) +- { +- inode = file->private_data; +- while( !Novfs_get_remove_entry(inode, &ino, info) ) +- { +- DbgPrint("Calling filedir-2 %llu with ino %d mode 0%o name %s\n", file->f_pos, ino, info->mode, info->name); +- if ( filldir(dirent, info->name, info->namelength, file->f_pos, ino, info->mode >> 12) < 0 ) +- { +- /* +- * put entry back on the list. +- */ +- name.len = info->namelength; +- name.name = info->name; +- name.hash = Novfs_internal_hash( &name ); +- Novfs_add_inode_entry(inode, &name, ino, info); +- +- break; +- } +- file->f_pos++; +- } +- } +- Novfs_Free(info); +- return(0); +- } +- +- if ( inode && inode->u.generic_ip ) +- { +- sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- if (0 == sessionId) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath(file->f_dentry); +- sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- uid = Scope_Get_Uid(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- else +- { +- sessionId = 0; +- uid = current->euid; +- } +- +- if ( IS_ROOT(file->f_dentry) || /* Root */ +- IS_ROOT(file->f_dentry->d_parent) || /* User */ +- IS_ROOT(file->f_dentry->d_parent->d_parent) ) /* Server */ +- { +- if ( IS_ROOT(file->f_dentry) ) +- { +- DbgPrint("Novfs_dir_readdir: Root directory\n"); +- list = Scope_Get_ScopeUsers(); +- type = USER_LIST; +- +- } else if ( IS_ROOT(file->f_dentry->d_parent) ) +- { +- DbgPrint("Novfs_dir_readdir: Parent is Root directory\n"); +- Novfs_Get_Connected_Server_List( &list, sessionId ); +- type = SERVER_LIST; +- } +- else +- { +- DbgPrint("Novfs_dir_readdir: Parent-Parent is Root directory\n"); +- Novfs_Get_Server_Volume_List(&file->f_dentry->d_name, &list, sessionId); +- type = VOLUME_LIST; +- } +- +- iLock = Novfs_lock_inode_cache( inode ); +- Novfs_invalidate_inode_cache( inode ); +- +- process_list(file, list, type, info, sessionId); +- } +- else +- { +- DbgPrint("Novfs_dir_readdir: Default directory\n"); +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- unsigned long enumHandle=0; +- +- iLock = Novfs_lock_inode_cache( inode ); +- Novfs_invalidate_inode_cache(inode); +- +- do +- { +- /* +- * Novfs_Get_Directory_List will return 0 when no error or -1 when +- * the last entry is returned. Otherwise it will return an error. +- */ +- info->namelength = 0; +- status = Novfs_Get_Directory_ListEx(path, &enumHandle, &count, &pinfo, sessionId); +- DbgPrint("Novfs_dir_readdir: Novfs_Get_Directory_List return 0x%x count=%d pinfo=0x%p\n", status, count, pinfo); +- iinfo = pinfo; +- while ( (0 == status) && pinfo && count-- ) +- { +- memcpy(info, pinfo, (int)((char *)&pinfo->name[pinfo->namelength]-(char *)pinfo)); +- pinfo = (PENTRY_INFO)&pinfo->name[pinfo->namelength]; +- name.len = info->namelength; +- name.name = info->name; +- name.hash = Novfs_internal_hash(&name); +- info->name[name.len] = '\0'; +- +- DbgPrint("Novfs_dir_readdir: Got %s\n", name.name); +- +- if ( Novfs_update_entry( inode, &name, 0, info )) +- { +- Novfs_add_inode_entry(inode, &name, (ino_t)InterlockedIncrement(&Novfs_Inode_Number), info); +- } +- } +- +- if (iinfo) +- { +- Novfs_Free(iinfo); +- } +- +- } while ( !status ); +- } +- } +- } +- +- if ( iLock ) +- { +- Novfs_free_invalid_entries( inode ); +- } +- +- switch ((int) file->f_pos) +- { +- case 0: +- DbgPrint("Calling filedir %llu with ino %d name .\n", file->f_pos, inode->i_ino); +- if (filldir(dirent, ".", 1, file->f_pos, inode->i_ino, DT_DIR) < 0) +- { +- break; +- } +- file->f_pos++; +- /* fallthrough */ +- case 1: +- DbgPrint("Calling filedir %llu with ino %d name ..\n", file->f_pos, parent_ino(file->f_dentry)); +- if (filldir(dirent, "..", 2, file->f_pos, parent_ino(file->f_dentry), DT_DIR) < 0) +- { +- break; +- } +- file->f_pos++; +- /* fallthrough */ +- +- default: +- status = 0; +- inter = NULL; +- +- if ( iLock ) +- { +- while( !Novfs_enumerate_inode_cache(inode, &inter, &ino, info) ) +- { +- DbgPrint("Calling filedir %llu with ino %d mode 0%o name %s\n", file->f_pos, ino, info->mode, info->name); +- if ( filldir(dirent, info->name, info->namelength, file->f_pos, ino, info->mode >> 12) < 0 ) +- { +- /* +- * Get the rest of the entries and put them in a fake +- * inode cache. +- */ +- file->private_data = (PDIR_CACHE)Novfs_Malloc(sizeof(struct inode) + sizeof(DIR_CACHE), GFP_KERNEL); +- if (file->private_data) +- { +- struct inode *dinode = file->private_data; +- PINODE_DATA id = (PINODE_DATA)((char *)file->private_data+sizeof(struct inode)); +- +- dinode->u.generic_ip = id; +- +- id->Scope = ((PINODE_DATA)inode->u.generic_ip)->Scope; +- id->Flags = 0; +- INIT_LIST_HEAD( &id->DirCache ); +- init_MUTEX( &id->DirCacheLock ); +- +- /* +- * Copy rest of the files. +- */ +- do +- { +- name.len = info->namelength; +- name.name = info->name; +- name.hash = Novfs_internal_hash( &name ); +- Novfs_add_inode_entry(dinode, &name, ino, info); +- } while( !Novfs_enumerate_inode_cache(inode, &inter, &ino, info) ); +- } +- +- break; +- } +- file->f_pos++; +- } +- } +- +- } +- +- if (iLock) +- { +- Novfs_unlock_inode_cache(inode); +- } +- } +- +- if (info) Novfs_Free( info ); +- if (buf) Novfs_Free( buf ); +- if (list) Novfs_Free( list ); +- +- return(status); +-} +- +- +-/*++======================================================================*/ +-int Novfs_dir_fsync(struct file * file, struct dentry *dentry, int datasync) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- return(simple_sync_file(file, dentry, datasync)); +-} +- +-/*++======================================================================*/ +-int do_open(struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PENTRY_INFO info=NULL; +- int retCode = -ENOENT; +- session_t session; +- char *path; +- struct dentry *parent; +- struct inode *inode; +- PINODE_DATA id; +- +- inode = file->f_dentry->d_inode; +- +- if (inode && inode->u.generic_ip) +- { +- id = (PINODE_DATA)file->f_dentry->d_inode->u.generic_ip; +- session = Scope_Get_SessionId(id->Scope); +- if (0 == session) +- { +- id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(id->Scope); +- } +- +- retCode = -ENOMEM; +- info = (PENTRY_INFO)Novfs_Malloc(sizeof(ENTRY_INFO) + PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (info) +- { +- path = Novfs_dget_path(file->f_dentry, info->name, PATH_LENGTH_BUFFER); +- if (path) +- { +- DbgPrint("do_open: %s\n", path); +- +- retCode = Novfs_Open_File( +- path, +- file->f_flags & ~O_EXCL, info, +- (unsigned long *)&file->private_data, +- session); +- DbgPrint("do_open: 0x%x 0x%x\n", retCode, file->private_data); +- if ( !retCode ) +- { +- if( !Novfs_Get_File_Info(path, info, session)) +- { +- update_inode(inode, info); +- } +- +- parent = dget_parent(file->f_dentry); +- +- if (parent && parent->d_inode) +- { +- struct inode *dir = parent->d_inode; +- Novfs_lock_inode_cache(dir); +- if (Novfs_update_entry(dir, &file->f_dentry->d_name, 0, info)) +- { +- Novfs_add_inode_entry(dir, &file->f_dentry->d_name, inode->i_ino, info); +- } +- +- Novfs_unlock_inode_cache(dir); +- } +- dput(parent); +- } +- } +- Novfs_Free(info); +- } +- } +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-ssize_t Novfs_f_read(struct file *file, char *buf, size_t len, loff_t *off) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- size_t thisread, totalread=0; +- loff_t offset = *off; +- struct inode *inode; +- session_t session; +- +- if (file->f_dentry && file->f_dentry->d_inode && file->f_dentry->d_inode->u.generic_ip) +- { +- DbgPrint("Novfs_f_read(0x%x 0x%p %d %lld %.*s)\n", (unsigned long)file->private_data, buf, len, offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name); +- +- if ( !file->private_data ) +- { +- totalread = (size_t)do_open( file ); +- if (totalread) +- { +- return(totalread); +- } +- } +- +- inode = file->f_dentry->d_inode; +- +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- +- while(len > 0 && (offset < inode->i_size) ) +- { +- thisread = len; +- if (Novfs_Read_File((unsigned long)file->private_data, buf, &thisread, &offset, 1, session) || !thisread) +- { +- break; +- } +- DbgPrint("Novfs_f_read thisread = 0x%x\n", thisread); +- len -= thisread; +- buf += thisread; +- offset += thisread; +- totalread += thisread; +- } +- } +- *off = offset; +- DbgPrint("Novfs_f_read return = 0x%x\n", totalread); +- +- return(totalread); +-} +- +-/*++======================================================================*/ +-ssize_t Novfs_f_write(struct file *file, const char *buf, size_t len, loff_t *off) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- size_t thiswrite, totalwrite=0; +- loff_t offset = *off; +- session_t session; +- struct inode *inode; +- int status; +- +- if (file->f_dentry && file->f_dentry->d_inode && file->f_dentry->d_inode->u.generic_ip) +- { +- inode = file->f_dentry->d_inode; +- +- if ( !file->private_data ) +- { +- totalwrite = (size_t)do_open( file ); +- if (totalwrite) +- { +- return(totalwrite); +- } +- } +- +- DbgPrint("Novfs_f_write(0x%x %d %lld %.*s)\n", (unsigned long)file->private_data, len, offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name); +- +- if (file->f_flags & O_APPEND) { +- offset = inode->i_size; +- DbgPrint("Novfs_f_write appending to end %lld %.*s\n", offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name); +- } +- +- +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- +- while(len > 0) +- { +- thiswrite = len; +- if ((status = Novfs_Write_File( +- (unsigned long)file->private_data, +- (unsigned char *)buf, +- &thiswrite, +- &offset, +- session)) || !thiswrite) +- { +- totalwrite = status; +- break; +- } +- DbgPrint("Novfs_f_write thiswrite = 0x%x\n", thiswrite); +- len -= thiswrite; +- buf += thiswrite; +- offset += thiswrite; +- totalwrite += thiswrite; +- if (offset > inode->i_size) +- { +- inode->i_size = offset; +- inode->i_blocks = (offset + inode->i_blksize - 1) >> inode->i_blkbits; +- } +- inode->i_mtime = inode->i_atime = CURRENT_TIME; +- ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; +- +- } +- } +- *off = offset; +- DbgPrint("Novfs_f_write return = 0x%x\n", totalwrite); +- +- return(totalwrite); +-} +- +-/*++======================================================================*/ +-int Novfs_f_readdir(struct file *file, void *data, filldir_t fill) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(data); +- UNUSED_VARIABLE(fill); +- return(-EISDIR); +-} +- +-/*++======================================================================*/ +-int Novfs_f_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- UNUSED_VARIABLE(inode); +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(cmd); +- UNUSED_VARIABLE(arg); +- DbgPrint("Novfs_f_ioctl: file=0x%x cmd=0x%x arg=0x%x", file, cmd, arg); +- +- return(-ENOSYS); +-} +- +-/*++======================================================================*/ +-int Novfs_f_mmap(struct file * file, struct vm_area_struct * vma) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -EINVAL; +- +- DbgPrint("Novfs_f_mmap: file=0x%x", file); +- +- retCode = generic_file_mmap(file, vma); +- +- DbgPrint("Novfs_f_mmap: retCode=0x%x\n", retCode); +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_f_open2(struct inode *inode, struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode; +- +- DbgPrint("Novfs_f_open: inode=0x%p file=0x%p dentry=0x%p dentry->d_inode=0x%p\n", inode, file, file->f_dentry, file->f_dentry->d_inode); +- if (file->f_dentry) +- { +- DbgPrint("Novfs_f_open: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode); +- } +- retCode = do_open(file); +- +- DbgPrint("Novfs_f_open: retCode=0x%x\n", retCode); +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_f_open(struct inode *inode, struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PENTRY_INFO info=NULL; +- int retCode = -ENOENT; +- session_t session; +- char *path; +- struct dentry *parent; +- PINODE_DATA id; +- +- DbgPrint("Novfs_f_open: inode=0x%p file=0x%p dentry=0x%p dentry->d_inode=0x%p\n", inode, file, file->f_dentry, file->f_dentry->d_inode); +- if (file->f_dentry) +- { +- DbgPrint("Novfs_f_open: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode); +- } +- +- if (inode && inode->u.generic_ip) +- { +- id = (PINODE_DATA)file->f_dentry->d_inode->u.generic_ip; +- session = Scope_Get_SessionId(id->Scope); +- if (0 == session) +- { +- id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(id->Scope); +- } +- +- info = (PENTRY_INFO)Novfs_Malloc(sizeof(ENTRY_INFO) + PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (info) +- { +- path = Novfs_dget_path(file->f_dentry, info->name, PATH_LENGTH_BUFFER); +- if (path) +- { +- DbgPrint("Novfs_f_open: %s\n", path); +- +- +- retCode = Novfs_Get_File_Info(path, info, session); +- if ( !retCode ) +- { +- if ( (O_TRUNC & file->f_flags) && S_ISREG(info->mode) && info->size ) +- { +- if (!Novfs_Truncate_File(path, strlen(path), session)) +- { +- info->size = 0; +- } +- } +- +- /* +- * Update inode info. +- */ +- update_inode(inode, info); +- +- file->private_data = NULL; +- +- parent = dget_parent(file->f_dentry); +- +- if (parent && parent->d_inode) +- { +- struct inode *dir = parent->d_inode; +- Novfs_lock_inode_cache(dir); +- if (Novfs_update_entry(dir, &file->f_dentry->d_name, 0, info)) +- { +- Novfs_add_inode_entry(dir, &file->f_dentry->d_name, inode->i_ino, info); +- } +- +- Novfs_unlock_inode_cache(dir); +- } +- dput(parent); +- +- if ( S_ISDIR(info->mode) ) +- { +- retCode = -EISDIR; +- } +- } +- else +- { +- if ( O_CREAT & file->f_flags ) +- { +- retCode = do_open(file); +- if (file->private_data) +- { +- Novfs_f_release(file->f_dentry->d_inode, file); +- file->private_data = NULL; +- } +- } +- } +- } +- Novfs_Free(info); +- } +- } +- DbgPrint("Novfs_f_open: retCode=0x%x\n", retCode); +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_f_flush(struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct inode *inode; +- +- UNUSED_VARIABLE(file); +- if (file->f_dentry) +- { +- inode = file->f_dentry->d_inode; +- DbgPrint("Novfs_f_flush: %.*s f_flags=0x%x f_mode=0%o i_mode=0%o\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode); +- } +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_f_release(struct inode *inode, struct file *file) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -EACCES; +- session_t session; +- PINODE_DATA id; +- +- DbgPrint("Novfs_f_release: path=%.*s handle=0x%x inode=0x%p\n", +- file->f_dentry->d_name.len, +- file->f_dentry->d_name.name, +- (unsigned long)file->private_data, file->f_dentry->d_inode); +- +- if ( file->f_dentry->d_inode && (id = file->f_dentry->d_inode->u.generic_ip)) +- { +- if (file->private_data) +- { +- session = Scope_Get_SessionId(id->Scope); +- if (0 == session) +- { +- id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(id->Scope); +- } +- +- //invalidate_remote_inode(file->f_dentry->d_inode); +- +- retCode = Novfs_Close_File((unsigned long)file->private_data, session); +- file->private_data = NULL; +- } +- else +- { +- retCode = 0; +- } +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_f_fsync(struct file *file, struct dentry *dentry, int datasync) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(dentry); +- UNUSED_VARIABLE(datasync); +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_f_llseek(struct file *file, loff_t offset, int origin) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- DbgPrint("Novfs_f_llseek: File=0x%x Name=%.*s offset=%lld origin=%d\n", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, offset, origin); +- return(generic_file_llseek(file, offset, origin)); +-} +- +-/*++======================================================================*/ +-int Novfs_f_lock(struct file *file, int cmd, struct file_lock *lock) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(cmd); +- UNUSED_VARIABLE(lock); +- return(-ENOSYS); +-} +- +-/*++======================================================================*/ +-int Novfs_a_readpage(struct file *file, struct page *page) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = 0; +- void *pbuf; +- struct inode *inode=NULL; +- struct dentry *dentry=NULL; +- loff_t offset; +- size_t len; +- session_t session=0; +- +- DbgPrint("Novfs_a_readpage: File=0x%x Name=%.*s Page=0x%x", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, page); +- +- dentry = file->f_dentry; +- +- if (dentry) +- { +- DbgPrint(" Dentry=0x%x Name=%.*s", dentry, dentry->d_name.len, dentry->d_name.name); +- if (dentry->d_inode) +- { +- inode = dentry->d_inode; +- } +- } +- +- +- +- if (inode) +- { +- DbgPrint(" Inode=0x%x Ino=%d", inode, inode->i_ino); +- +- if (inode->u.generic_ip) +- { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- } +- } +- +- DbgPrint("\n"); +- +- if ( !file->private_data ) +- { +- retCode = (size_t)do_open( file ); +- } +- +- if (file->private_data && !PageUptodate(page)) +- { +- pbuf = kmap(page); +- +- offset = page->index << PAGE_CACHE_SHIFT; +- len = PAGE_CACHE_SIZE; +- +- retCode = Novfs_Read_File((unsigned long)file->private_data, pbuf, &len, &offset, 0, session); +- if ( len && (len < PAGE_CACHE_SIZE) ) +- { +- memset(&((char *)pbuf)[len], 0, PAGE_CACHE_SIZE-len); +- } +- +- kunmap(page); +- flush_dcache_page(page); +- SetPageUptodate(page); +- } +- unlock_page(page); +- +- DbgPrint("Novfs_a_readpage: retCode=%d\n", retCode); +- return (retCode); +- +-} +- +-/*++======================================================================*/ +-int Novfs_i_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *path, *buf; +- ENTRY_INFO info; +- unsigned long handle; +- session_t session; +- int retCode = -EACCES; +- +- +- DbgPrint("Novfs_i_create: mode=0%o flags=0%o %.*s\n", mode, nd->NDOPENFLAGS, dentry->d_name.len, dentry->d_name.name); +- +- if ( IS_ROOT(dentry) || /* Root */ +- IS_ROOT(dentry->d_parent) || /* User */ +- IS_ROOT(dentry->d_parent->d_parent) || /* Server */ +- IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ +- { +- return(-EACCES); +- } +- +- if (mode | S_IFREG) +- { +- if (dir->u.generic_ip) +- { +- session = Scope_Get_SessionId( ((PINODE_DATA)dir->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)dir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)dir->u.generic_ip)->Scope); +- } +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- retCode = Novfs_Open_File(path, nd->NDOPENFLAGS|O_RDWR, &info, &handle, session); +- if ( !retCode && handle ) +- { +- Novfs_Close_File(handle, session); +- if (!Novfs_i_mknod(dir, dentry, mode | S_IFREG, 0)) +- { +- if (dentry->d_inode) +- { +- ((PINODE_DATA)dentry->d_inode->u.generic_ip)->Flags |= UPDATE_INODE; +- } +- } +- } +- } +- Novfs_Free(buf); +- } +- } +- } +- return( retCode ); +-} +- +-/*++======================================================================*/ +-void update_inode(struct inode *Inode, PENTRY_INFO Info) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- static char dbuf[128]; +- +- DbgPrint("update_inode: Inode=0x%x I_ino=%d\n", Inode, Inode->i_ino); +- +- DbgPrint("update_inode: atime=%s\n", ctime_r(&Info->atime.tv_sec, dbuf)); +- DbgPrint("update_inode: ctime=%s\n", ctime_r(&Info->ctime.tv_sec, dbuf)); +- DbgPrint("update_inode: mtime=%s\n", ctime_r(&Info->mtime.tv_sec, dbuf)); +- DbgPrint("update_inode: size=%lld\n", Info->size); +- DbgPrint("update_inode: mode=0%o\n", Info->mode); +- +- Inode->i_mode = Info->mode; +- Inode->i_size = Info->size; +- Inode->i_atime = Info->atime; +- Inode->i_ctime = Info->ctime; +- Inode->i_mtime = Info->mtime; +- Inode->i_blocks = (u_long)(Info->size >> (loff_t)Inode->i_blkbits); +- Inode->i_bytes = Info->size & (Inode->i_blksize - 1); +- +- DbgPrint("update_inode: i_blksize=%d\n", Inode->i_blksize); +- DbgPrint("update_inode: i_blkbits=%d\n", Inode->i_blkbits); +- DbgPrint("update_inode: i_blocks=%d\n", Inode->i_blocks); +- DbgPrint("update_inode: i_bytes=%d\n", Inode->i_bytes); +-} +- +-/*++======================================================================*/ +-struct dentry * Novfs_i_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct dentry *retVal = ERR_PTR(-ENOENT); +- struct dentry *parent; +- PENTRY_INFO info=NULL; +- PINODE_DATA id; +- struct inode *inode=NULL; +- uid_t uid=current->euid; +- ino_t ino=0; +- struct qstr name; +- +- DbgPrint("Novfs_i_lookup: dir 0x%x %d name %.*s hash %d inode 0x%0p\n", dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name, dentry->d_name.hash, dentry->d_inode); +- +- if (dir && (id = dir->u.generic_ip) ) +- { +- retVal = 0; +- if ( IS_ROOT( dentry )) +- { +- DbgPrint("Novfs_i_lookup: Root entry=0x%x\n", Novfs_root); +- inode = Novfs_root->d_inode; +- return(0); +- } +- else +- { +- info = Novfs_Malloc(sizeof(ENTRY_INFO)+PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (info) +- { +- if ( NULL == (retVal = ERR_PTR(verify_dentry( dentry, 1 )))) +- { +- name.name = dentry->d_name.name; +- name.len = dentry->d_name.len; +- name.hash = Novfs_internal_hash(&name); +- +- if (Novfs_lock_inode_cache( dir )) +- { +- if ( !Novfs_get_entry(dir, &name, &ino, info) ) +- { +- inode = ilookup(dentry->d_sb, ino); +- if ( inode ) +- { +- update_inode(inode, info); +- } +- } +- Novfs_unlock_inode_cache( dir ); +- } +- +- if ( !inode && ino ) +- { +- uid = Scope_Get_Uid( id->Scope ); +- if (Novfs_lock_inode_cache( dir )) +- { +- inode = Novfs_get_inode(dentry->d_sb, info->mode, 0, uid, ino, &name); +- if ( inode ) +- { +- if ( !Novfs_get_entry(dir, &dentry->d_name, &ino, info) ) +- { +- update_inode(inode, info); +- } +- } +- Novfs_unlock_inode_cache( dir ); +- } +- } +- } +- } +- } +- } +- +- if ( !retVal ) +- { +- dentry->d_op = &Novfs_dentry_operations; +- if (inode) +- { +- parent = dget_parent(dentry); +- Novfs_d_add(dentry->d_parent, dentry, inode, 1); +- dput(parent); +- } +- else +- { +- d_add( dentry, inode); +- } +- } +- +- if (info) Novfs_Free(info); +- +- DbgPrint("Novfs_i_lookup: inode=0x%x dentry->d_inode=0x%x return=0x%x\n", dir, dentry->d_inode, retVal); +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int Novfs_i_unlink(struct inode *dir, struct dentry *dentry) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOENT; +- struct inode *inode; +- session_t session; +- char *path, *buf; +- uint64_t t64; +- +- DbgPrint("Novfs_i_unlink: dir=0x%x dir->i_ino=%d %.*s\n", dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name); +- DbgPrint("Novfs_i_unlink: IS_ROOT(dentry)=%d\n", IS_ROOT(dentry)); +- DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent)=%d\n", IS_ROOT(dentry->d_parent)); +- DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent->d_parent)=%d\n", IS_ROOT(dentry->d_parent->d_parent)); +- DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent->d_parent->d_parent)=%d\n", IS_ROOT(dentry->d_parent->d_parent->d_parent) ); +- +- if ( IS_ROOT(dentry) || /* Root */ +- IS_ROOT(dentry->d_parent) || /* User */ +- (!IS_ROOT(dentry->d_parent->d_parent) && /* Server */ +- IS_ROOT(dentry->d_parent->d_parent->d_parent)) ) /* Volume */ +- { +- return(-EACCES); +- } +- +- inode = dentry->d_inode; +- if ( inode ) +- { +- DbgPrint("Novfs_i_unlink: dir=0x%x dir->i_ino=%d inode=0x%x ino=%d\n", dir, dir->i_ino, inode, inode->i_ino); +- if (inode->u.generic_ip) +- { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- DbgPrint("Novfs_i_unlink: path %s mode 0%o\n", path, inode->i_mode); +- if (IS_ROOT(dentry->d_parent->d_parent)) +- { +- retCode = do_logout(&dentry->d_name); +- } +- else +- { +- retCode = Novfs_Delete(path, S_ISDIR(inode->i_mode), session); +- } +- if ( !retCode || IS_DEADDIR(inode)) +- { +- Novfs_remove_inode_entry(dir, &dentry->d_name, 0); +- dentry->d_time = 0; +- t64 = 0; +- Scope_Set_UserSpace(&t64, &t64, &t64, &t64); +- retCode = 0; +- } +- } +- Novfs_Free(buf); +- } +- } +- } +- +- DbgPrint("Novfs_i_unlink: retCode 0x%x\n", retCode); +- return (retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_i_mkdir(struct inode *dir, struct dentry *dentry, int mode) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *path, *buf; +- session_t session; +- int retCode=0; +- struct inode *inode; +- ENTRY_INFO info; +- uid_t uid; +- +- DbgPrint("Novfs_i_mkdir: dir=0x%p ino=%d dentry=0x%p %.*s mode=0%o\n", dir, dir->i_ino, dentry, dentry->d_name.len, dentry->d_name.name, mode); +- +- if ( IS_ROOT(dentry) || /* Root */ +- IS_ROOT(dentry->d_parent) || /* User */ +- IS_ROOT(dentry->d_parent->d_parent) || /* Server */ +- IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ +- { +- return(-EACCES); +- } +- +- mode |= S_IFDIR; +- mode &= (S_IFMT | S_IRWXU); +- if ( dir->u.generic_ip ) +- { +- session = Scope_Get_SessionId( ((PINODE_DATA)dir->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)dir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)dir->u.generic_ip)->Scope); +- } +- +- uid = Scope_Get_Uid( ((PINODE_DATA)dir->u.generic_ip)->Scope); +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- DbgPrint("Novfs_i_mkdir: path %s\n", path); +- retCode = Novfs_Create(path, S_ISDIR(mode), session); +- if ( !retCode ) +- { +- retCode = Novfs_Get_File_Info(path, &info, session ); +- if ( !retCode ) +- { +- retCode = Novfs_i_mknod(dir, dentry, mode, 0); +- inode = dentry->d_inode; +- if (inode) +- { +- update_inode(inode, &info); +- ((PINODE_DATA)inode->u.generic_ip)->Flags &= ~UPDATE_INODE; +- +- dentry->d_time = jiffies+(File_update_timeout*HZ); +- +- Novfs_lock_inode_cache(dir); +- if (Novfs_update_entry( dir, &dentry->d_name, 0, &info )) +- { +- Novfs_add_inode_entry(dir, &dentry->d_name, inode->i_ino, &info); +- } +- Novfs_unlock_inode_cache(dir); +- } +- +- } +- } +- } +- Novfs_Free(buf); +- } +- } +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_i_rmdir(struct inode *inode, struct dentry *dentry) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- return(Novfs_i_unlink(inode, dentry)); +-} +- +-/*++======================================================================*/ +-int Novfs_i_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct inode *inode=NULL; +- int retCode = -EACCES; +- uid_t uid; +- struct dentry *parent; +- +- if ( IS_ROOT(dentry) || /* Root */ +- IS_ROOT(dentry->d_parent) || /* User */ +- IS_ROOT(dentry->d_parent->d_parent) || /* Server */ +- IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ +- { +- return(-EACCES); +- } +- +- if ( ((PINODE_DATA)dir->u.generic_ip) ) +- { +- uid = Scope_Get_Uid( ((PINODE_DATA)dir->u.generic_ip)->Scope); +- if (mode & (S_IFREG | S_IFDIR)) +- { +- inode = Novfs_get_inode(dir->i_sb, mode, dev, uid, 0, &dentry->d_name); +- } +- } +- +- if (inode) +- { +- ENTRY_INFO info; +- +- dentry->d_op = &Novfs_dentry_operations; +- parent = dget_parent(dentry); +- Novfs_d_add(parent, dentry, inode, 0); +- memset(&info, 0, sizeof(info)); +- info.mode = inode->i_mode; +- Novfs_lock_inode_cache( dir ); +- Novfs_add_inode_entry( dir, &dentry->d_name, inode->i_ino, &info); +- Novfs_unlock_inode_cache( dir ); +- +- dput(parent); +- +- retCode = 0; +- } +- DbgPrint("Novfs_i_mknod: return 0x%x\n", retCode); +- return retCode; +-} +- +-/*++======================================================================*/ +-int Novfs_i_rename(struct inode *odir, struct dentry *od, struct inode *ndir, struct dentry *nd) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = -ENOTEMPTY; +- char *newpath, *newbuf, *newcon; +- char *oldpath, *oldbuf, *oldcon; +- struct qstr newname, oldname; +- PENTRY_INFO info=NULL; +- int oldlen, newlen; +- session_t session; +- ino_t ino; +- +- +- if ( IS_ROOT(od) || /* Root */ +- IS_ROOT(od->d_parent) || /* User */ +- IS_ROOT(od->d_parent->d_parent) || /* Server */ +- IS_ROOT(od->d_parent->d_parent->d_parent) ) /* Volume */ +- { +- return(-EACCES); +- } +- +- DbgPrint("Novfs_i_rename: odir=0x%p ino=%d ndir=0x%p ino=%d\n", odir, odir->i_ino, ndir, ndir->i_ino); +- +- oldbuf = Novfs_Malloc(PATH_LENGTH_BUFFER*2, GFP_KERNEL); +- newbuf = oldbuf+PATH_LENGTH_BUFFER; +- if ( oldbuf && newbuf ) +- { +- oldpath = Novfs_dget_path(od, oldbuf, PATH_LENGTH_BUFFER); +- newpath = Novfs_dget_path(nd, newbuf, PATH_LENGTH_BUFFER); +- if (oldpath && newpath) +- { +- oldlen = PATH_LENGTH_BUFFER-(int)(oldpath-oldbuf); +- newlen = PATH_LENGTH_BUFFER-(int)(newpath-newbuf); +- +- DbgPrint("Novfs_i_rename: odir=0x%x od->inode=0x%x\n", odir, od->d_inode); +- DbgPrint("Novfs_i_rename: old path %s\n", oldpath); +- DbgPrint("Novfs_i_rename: new path %s\n", newpath); +- +- /* +- * Check to see if two different servers or different volumes +- */ +- newcon = strchr(newpath+1, '\\'); +- oldcon = strchr(oldpath+1, '\\'); +- DbgPrint("Novfs_i_rename: newcon=0x%x newpath=0x%x\n", newcon, newpath); +- DbgPrint("Novfs_i_rename: oldcon=0x%x oldpath=0x%x\n", oldcon, oldpath); +- retCode = -EXDEV; +- if ( newcon && oldcon && ((int)(newcon-newpath) == (int)(oldcon-oldpath)) ) +- { +- newcon = strchr(newcon+1, '\\'); +- oldcon = strchr(oldcon+1, '\\'); +- DbgPrint("Novfs_i_rename2: newcon=0x%x newpath=0x%x\n", newcon, newpath); +- DbgPrint("Novfs_i_rename2: oldcon=0x%x oldpath=0x%x\n", oldcon, oldpath); +- if ( newcon && oldcon && ((int)(newcon-newpath) == (int)(oldcon-oldpath)) ) +- { +- newname.name = newpath; +- newname.len = (int)(newcon-newpath); +- newname.hash = 0; +- +- oldname.name = oldpath; +- oldname.len = (int)(oldcon-oldpath); +- oldname.hash = 0; +- if ( !Novfs_d_strcmp(&newname, &oldname)) +- { +- +- if ( od->d_inode && od->d_inode->u.generic_ip ) +- { +- +- if (nd->d_inode && nd->d_inode->u.generic_ip) +- { +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)ndir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( nd ); +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); +- } +- +- retCode = Novfs_Delete(newpath, S_ISDIR(nd->d_inode->i_mode), session); +- } +- +- +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)ndir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( nd ); +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); +- } +- retCode = Novfs_Rename_File( +- S_ISDIR(od->d_inode->i_mode), +- oldpath, +- oldlen-1, +- newpath, +- newlen-1, +- session); +- +- if ( !retCode ) +- { +- info = (PENTRY_INFO)oldbuf; +- od->d_time = 0; +- Novfs_remove_inode_entry(odir, &od->d_name, 0); +- Novfs_Get_File_Info(newpath, info, session); +- nd->d_time = jiffies+(File_update_timeout*HZ); +- if (Novfs_update_entry(ndir, &nd->d_name, 0, info)) +- { +- if (nd->d_inode && nd->d_inode->i_ino) +- { +- ino = nd->d_inode->i_ino; +- } +- else +- { +- ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); +- } +- Novfs_add_inode_entry(ndir, &nd->d_name, ino, info); +- } +- } +- } +- } +- } +- } +- } +- } +- +- if (oldbuf) Novfs_Free(oldbuf); +- +- return( retCode ); +-} +- +-/*++======================================================================*/ +-int Novfs_i_permission(struct inode *inode, int mask) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode=0; +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-int Novfs_i_setattr(struct dentry *dentry, struct iattr *attr) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *path, *buf; +- struct inode *inode=dentry->d_inode; +- char atime_buf[32]; +- char mtime_buf[32]; +- char ctime_buf[32]; +- unsigned int ia_valid = attr->ia_valid; +- session_t session; +- int retVal = 0; +- +- if ( IS_ROOT(dentry) || /* Root */ +- IS_ROOT(dentry->d_parent) || /* User */ +- IS_ROOT(dentry->d_parent->d_parent) || /* Server */ +- IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ +- { +- return(-EACCES); +- } +- +- if (inode && inode->u.generic_ip) +- { +- session = Scope_Get_SessionId( ((PINODE_DATA)inode->u.generic_ip)->Scope); +- if (0 == session) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- } +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- strcpy(atime_buf, "Unspecified"); +- strcpy(mtime_buf, "Unspecified"); +- strcpy(ctime_buf, "Unspecified"); +- if (attr->ia_valid & ATTR_ATIME) +- { +- ctime_r(&attr->ia_atime.tv_sec, atime_buf); +- } +- if (attr->ia_valid & ATTR_MTIME) +- { +- ctime_r(&attr->ia_mtime.tv_sec, mtime_buf); +- } +- if (attr->ia_valid & ATTR_CTIME) +- { +- ctime_r(&attr->ia_ctime.tv_sec, ctime_buf); +- } +- DbgPrint("Novfs_i_setattr: %s\n" \ +- " ia_valid: 0x%x\n" \ +- " ia_mode: 0%o\n" \ +- " ia_uid: %d\n" \ +- " ia_gid: %d\n" \ +- " ia_size: %lld\n" \ +- " ia_atime: %s\n" \ +- " ia_mtime: %s\n" \ +- " ia_ctime: %s\n", +- path, +- attr->ia_valid, +- attr->ia_mode, +- attr->ia_uid, +- attr->ia_gid, +- attr->ia_size, +- atime_buf, +- mtime_buf, +- ctime_buf); +- +- if ( !(retVal = Novfs_Set_Attr(path, attr, session) ) ) +- { +- ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; +- +- if (ia_valid & ATTR_SIZE) +- { +- inode->i_size = attr->ia_size; +- inode->i_blocks = (u_long)(inode->i_size >> (loff_t)inode->i_blkbits); +- inode->i_bytes = inode->i_size & (inode->i_blksize - 1); +- +- } +- if (ia_valid & ATTR_ATIME) +- inode->i_atime = attr->ia_atime; +- if (ia_valid & ATTR_MTIME) +- inode->i_mtime = attr->ia_mtime; +- if (ia_valid & ATTR_CTIME) +- inode->i_ctime = attr->ia_ctime; +- if (ia_valid & ATTR_MODE) { +- inode->i_mode = attr->ia_mode & (S_IFMT | S_IRWXU); +- } +- } +- } +- } +- Novfs_Free(buf); +- } +- +- return(retVal); +-} +- +-/*++======================================================================*/ +-int Novfs_i_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode = 0; +- char atime_buf[32]; +- char mtime_buf[32]; +- char ctime_buf[32]; +- struct inode *inode = dentry->d_inode; +- +- ENTRY_INFO info; +- char *path, *buf; +- session_t session; +- PINODE_DATA id; +- +- if ( !IS_ROOT(dentry) && +- !IS_ROOT(dentry->d_parent) ) +- { +- session = 0; +- id = dentry->d_inode->u.generic_ip; +- +- if (id && (id->Flags & UPDATE_INODE) ) +- { +- session = Scope_Get_SessionId( id->Scope ); +- +- if (0 == session) +- { +- id->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(id->Scope); +- } +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- retCode = Novfs_Get_File_Info(path, &info, session ); +- if ( !retCode ) +- { +- update_inode(inode, &info); +- id->Flags &= ~UPDATE_INODE; +- } +- } +- Novfs_Free(buf); +- } +- } +- } +- +- kstat->ino = inode->i_ino; +- kstat->dev = inode->i_sb->s_dev; +- kstat->mode = inode->i_mode; +- kstat->nlink = inode->i_nlink; +- kstat->uid = inode->i_uid; +- kstat->gid = inode->i_gid; +- kstat->rdev = inode->i_rdev; +- kstat->size = i_size_read(inode); +- kstat->atime = inode->i_atime; +- kstat->mtime = inode->i_mtime; +- kstat->ctime = inode->i_ctime; +- kstat->blksize = inode->i_blksize; +- kstat->blocks = inode->i_blocks; +- if (inode->i_bytes) +- { +- kstat->blocks++; +- } +- ctime_r(&kstat->atime.tv_sec, atime_buf); +- ctime_r(&kstat->mtime.tv_sec, mtime_buf); +- ctime_r(&kstat->ctime.tv_sec, ctime_buf); +- +- +- DbgPrint("Novfs_i_getattr: 0x%x <%.*s>\n" \ +- " ino: %d\n" \ +- " dev: 0x%x\n" \ +- " mode: 0%o\n" \ +- " nlink: 0x%x\n" \ +- " uid: 0x%x\n" \ +- " gid: 0x%x\n" \ +- " rdev: 0x%x\n" \ +- " size: 0x%llx\n" \ +- " atime: %s\n" \ +- " mtime: %s\n" \ +- " ctime: %s\n" \ +- " blksize: 0x%x\n" \ +- " blocks: 0x%x\n", +- retCode, dentry->d_name.len, dentry->d_name.name, +- kstat->ino, +- kstat->dev, +- kstat->mode, +- kstat->nlink, +- kstat->uid, +- kstat->gid, +- kstat->rdev, +- kstat->size, +- atime_buf, +- mtime_buf, +- ctime_buf, +- kstat->blksize, +- kstat->blocks); +- return( retCode ); +-} +- +- +-/*++======================================================================*/ +-int Novfs_i_revalidate(struct dentry *dentry) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- +- DbgPrint("Novfs_i_revalidate: name %.*s\n", dentry->d_name.len, dentry->d_name.name); +- +- return(0); +-} +- +-/*++======================================================================*/ +-void Novfs_read_inode(struct inode *inode) +-/* +- * Arguments: +- * +- * Returns: nothing +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: Superblock operation +- * +- *=======================================================================-*/ +-{ +- DbgPrint( "Novfs_read_inode: 0x%x %d\n", inode, inode->i_ino); +-} +- +-/*++======================================================================*/ +-void Novfs_write_inode(struct inode *inode) +-/* +- * Arguments: +- * +- * Returns: nothing +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: Superblock operation +- * +- *=======================================================================-*/ +-{ +- DbgPrint( "Novfs_write_inode: Inode=0x%x Ino=%d\n", inode, inode->i_ino); +-} +- +-/*++======================================================================*/ +-int Novfs_notify_change(struct dentry *dentry, struct iattr *attr) +-/* +- * Arguments: +- * +- * Returns: error code +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: Superblock operation +- * +- *=======================================================================-*/ +-{ +- struct inode *inode = dentry->d_inode; +- +- DbgPrint( "Novfs_notify_change: Dentry=0x%x Name=%.*s Inode=0x%x Ino=%d ia_valid=0x%x\n", +- dentry, dentry->d_name.len, dentry->d_name.name,inode, inode->i_ino, attr->ia_valid); +- return(0); +-} +- +-/*++======================================================================*/ +-void Novfs_clear_inode(struct inode *inode) +-/* +- * Arguments: sb - pointer to the super_block +- * buf - pointer to the statfs buffer +- * +- * Returns: 0 +- * +- * Abstract: Called when statfs(2) system called. +- * +- * Notes: +- * +- * Environment: Superblock operation +- * +- *========================================================================*/ +-{ +- InodeCount--; +- +- if ( inode->u.generic_ip ) +- { +- PINODE_DATA id=inode->u.generic_ip; +- +- DbgPrint("Novfs_clear_inode: inode=0x%x ino=%d Scope=0x%p Name=%s\n", inode, inode->i_ino, id->Scope, id->Name); +- +- Novfs_free_inode_cache(inode); +- +- down( &InodeList_lock ); +- list_del( &id->IList ); +- up( &InodeList_lock ); +- +- +- Novfs_Free(inode->u.generic_ip); +- inode->u.generic_ip = NULL; +- +- remove_inode_hash( inode ); +- +- } +- else +- { +- DbgPrint("Novfs_clear_inode: inode=0x%x ino=%d\n", inode, inode->i_ino); +- } +-} +- +-/*++======================================================================*/ +-int +-NO_TRACE +-Novfs_show_options( struct seq_file *s, struct vfsmount *m ) +-/* +- * Arguments: +- * +- * Returns: 0 +- * +- * Abstract: Called when /proc/mounts is read +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *buf, *path, *tmp; +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = d_path(m->mnt_root, m, buf, PATH_LENGTH_BUFFER); +- if (path) +- { +- if ( !Novfs_CurrentMount || (Novfs_CurrentMount && strcmp(Novfs_CurrentMount, path))) +- { +- DbgPrint("Novfs_show_options: %.*s %.*s %s\n", m->mnt_root->d_name.len, m->mnt_root->d_name.name, +- m->mnt_mountpoint->d_name.len, m->mnt_mountpoint->d_name.name, path); +- tmp = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER - (int)(path-buf), GFP_KERNEL); +- if (tmp) +- { +- strcpy(tmp, path); +- path = Novfs_CurrentMount; +- Novfs_CurrentMount = tmp; +- Daemon_SetMountPoint( Novfs_CurrentMount ); +- +- if (path) +- { +- Novfs_Free(path); +- } +- } +- } +- } +- Novfs_Free( buf ); +- } +- return(0); +-} +- +-/*++======================================================================*/ +-int Novfs_statfs(struct super_block *sb, struct kstatfs *buf) +-/* +- * Arguments: sb - pointer to the super_block +- * buf - pointer to the statfs buffer +- * +- * Returns: 0 +- * +- * Abstract: Called when statfs(2) system called. +- * +- * Notes: +- * +- * Environment: Superblock operation +- * +- *========================================================================*/ +-{ +- uint64_t td, fd, te, fe; +- +- UNUSED_VARIABLE(sb); +- +- DbgPrint("Novfs_statfs:\n"); +- +- td = fd = te = fe = 0; +- +- Scope_Get_UserSpace( &td, &fd, &te, &fe ); +- +- DbgPrint("td=%llu\n", td); +- DbgPrint("fd=%llu\n", fd); +- DbgPrint("te=%llu\n", te); +- DbgPrint("fe=%llu\n", fd); +- +- buf->f_type = sb->s_magic; +- buf->f_bsize = sb->s_blocksize; +- buf->f_namelen = NW_MAX_PATH_LENGTH; +- buf->f_blocks = (sector_t)(td + (uint64_t)(sb->s_blocksize-1)) >> (uint64_t)sb->s_blocksize_bits; +- buf->f_bfree = (sector_t)fd >> (uint64_t)sb->s_blocksize_bits; +- buf->f_bavail = (sector_t)buf->f_bfree; +- buf->f_files = (sector_t)te; +- buf->f_ffree = (sector_t)fe; +- buf->f_frsize = sb->s_blocksize; +- if (te > 0xffffffff) +- buf->f_files = 0xffffffff; +- +- if (fe > 0xffffffff) +- buf->f_ffree = 0xffffffff; +- +- +- DbgPrint("f_type: 0x%x\n", buf->f_type); +- DbgPrint("f_bsize: %u\n", buf->f_bsize); +- DbgPrint("f_namelen: %d\n", buf->f_namelen); +- DbgPrint("f_blocks: %llu\n", buf->f_blocks); +- DbgPrint("f_bfree: %llu\n", buf->f_bfree); +- DbgPrint("f_bavail: %llu\n", buf->f_bavail); +- DbgPrint("f_files: %llu\n", buf->f_files); +- DbgPrint("f_ffree: %llu\n", buf->f_ffree); +- DbgPrint("f_frsize: %u\n", buf->f_frsize); +- +- return 0; +-} +- +-/*++======================================================================*/ +-struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t Uid, ino_t ino, struct qstr *name) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *=======================================================================-*/ +-{ +- struct inode * inode = new_inode(sb); +- +- if (inode) +- { +- InodeCount++; +- inode->i_mode = mode; +- inode->i_uid = Uid; +- inode->i_gid = 0; +- inode->i_blksize = sb->s_blocksize; +- inode->i_blkbits = sb->s_blocksize_bits; +- inode->i_size = 0; +- inode->i_blocks = 0; +- inode->i_rdev = 0; +- inode->i_ino = (ino) ? ino: (ino_t)InterlockedIncrement(&Novfs_Inode_Number); +- inode->i_mapping->a_ops = &Novfs_aops; +- inode->i_atime.tv_sec = 0; +- inode->i_atime.tv_nsec = 0; +- inode->i_mtime = inode->i_ctime = inode->i_atime; +- +- DbgPrint("Novfs_get_inode: Inode=0x%p I_ino=%d len=%d\n", inode, inode->i_ino, name->len); +- +- if (NULL != (inode->u.generic_ip = Novfs_Malloc(sizeof(INODE_DATA)+name->len, GFP_KERNEL))) +- { +- PINODE_DATA id; +- id = inode->u.generic_ip; +- +- DbgPrint("Novfs_get_inode: u.generic_ip 0x%p\n", id); +- +- id->Scope = NULL; +- id->Flags = 0; +- id->Inode = inode; +- INIT_LIST_HEAD( &id->DirCache ); +- init_MUTEX( &id->DirCacheLock ); +- down( &InodeList_lock ); +- +- list_add_tail(&id->IList, &InodeList); +- up( &InodeList_lock ); +- +- id->Name[0] = '\0'; +- +- memcpy(id->Name, name->name, name->len); +- id->Name[name->len] = '\0'; +- +- DbgPrint("Novfs_get_inode: name %s\n", id->Name); +- } +- +- insert_inode_hash(inode); +- +- switch (mode & S_IFMT) { +- +- case S_IFREG: +- inode->i_op = &Novfs_file_inode_operations; +- inode->i_fop = &Novfs_file_operations; +- break; +- +- case S_IFDIR: +- inode->i_op = &Novfs_inode_operations; +- inode->i_fop = &Novfs_dir_operations; +- inode->i_blksize = 0; +- inode->i_blkbits = 0; +- break; +- +- default: +- init_special_inode(inode, mode, dev); +- break; +- } +- +- DbgPrint("Novfs_get_inode: size=%lld\n", inode->i_size); +- DbgPrint("Novfs_get_inode: mode=0%o\n", inode->i_mode); +- DbgPrint("Novfs_get_inode: i_blksize=%d\n", inode->i_blksize); +- DbgPrint("Novfs_get_inode: i_blkbits=%d\n", inode->i_blkbits); +- DbgPrint("Novfs_get_inode: i_blocks=%d\n", inode->i_blocks); +- DbgPrint("Novfs_get_inode: i_bytes=%d\n", inode->i_bytes); +- } +- +- DbgPrint("Novfs_get_inode: 0x%p %d\n", inode, inode->i_ino); +- return (inode); +-} +- +-/*++======================================================================*/ +-int Novfs_fill_super (struct super_block *SB, void *Data, int Silent) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct inode * inode; +- struct dentry *server, *tree; +- struct qstr name; +-/* PINODE_DATA id; +-*/ +- ENTRY_INFO info; +- +- UNUSED_VARIABLE(Data); +- UNUSED_VARIABLE(Silent); +- +- SB->s_blocksize = PAGE_CACHE_SIZE; +- SB->s_blocksize_bits = PAGE_CACHE_SHIFT; +- SB->s_maxbytes = 0xFFFFFFFFFFFFFFFFULL; /* Max file size */ +- SB->s_op = &Novfs_ops; +- SB->s_flags |= (MS_NODIRATIME | MS_NODEV | MS_POSIXACL); +- SB->s_magic = NOVFS_MAGIC; +- +- +- name.len = 1; +- name.name = "/"; +- +- inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name); +- if (!inode) +- { +- return( -ENOMEM ); +- } +- +- Novfs_root = d_alloc_root(inode); +- +- if (!Novfs_root) +- { +- iput(inode); +- return( -ENOMEM ); +- } +- Novfs_root->d_time = jiffies+(File_update_timeout*HZ); +- +- inode->i_atime = +- inode->i_ctime = +- inode->i_mtime = CURRENT_TIME; +- +- +- SB->s_root = Novfs_root; +- +- DbgPrint( "Novfs_fill_super: root 0x%x\n", Novfs_root); +- +- if (Novfs_root) +- { +- Novfs_root->d_op = &Novfs_dentry_operations; +- +- name.name = SERVER_DIRECTORY_NAME; +- name.len = strlen(SERVER_DIRECTORY_NAME); +- name.hash = Novfs_internal_hash( &name ); +- +- inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name); +- if (inode) +- { +- info.mode = inode->i_mode; +- info.namelength = 0; +- inode->i_size = info.size = 0; +- inode->i_uid = info.uid = 0; +- inode->i_gid = info.gid = 0; +- inode->i_atime = info.atime = +- inode->i_ctime = info.ctime = +- inode->i_mtime = info.mtime = CURRENT_TIME; +- +- server = d_alloc(Novfs_root, &name); +- if (server) +- { +- server->d_op = &Novfs_dentry_operations; +- server->d_time = 0xffffffff; +- d_add(server, inode); +- DbgPrint( "Novfs_fill_super: d_add %s 0x%x\n", SERVER_DIRECTORY_NAME, server); +- Novfs_add_inode_entry(Novfs_root->d_inode, &name, inode->i_ino, &info); +- } +- } +- +- name.name = TREE_DIRECTORY_NAME; +- name.len = strlen(TREE_DIRECTORY_NAME); +- name.hash = Novfs_internal_hash( &name ); +- +- inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name); +- if (inode) +- { +- info.mode = inode->i_mode; +- info.namelength = 0; +- inode->i_size = info.size = 0; +- inode->i_uid = info.uid = 0; +- inode->i_gid = info.gid = 0; +- inode->i_atime = info.atime = +- inode->i_ctime = info.ctime = +- inode->i_mtime = info.mtime = CURRENT_TIME; +- tree = d_alloc(Novfs_root, &name); +- if (tree) +- { +- tree->d_op = &Novfs_dentry_operations; +- tree->d_time = 0xffffffff; +- +- d_add(tree, inode); +- DbgPrint( "Novfs_fill_super: d_add %s 0x%x\n", TREE_DIRECTORY_NAME, tree); +- Novfs_add_inode_entry(Novfs_root->d_inode, &name, inode->i_ino, &info); +- } +- } +- } +- +- return( 0 ); +-} +- +-/*++======================================================================*/ +-struct super_block *Novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct super_block *sb; +- UNUSED_VARIABLE(Dev_name); +- +- sb = get_sb_nodev(Fstype, Flags, Data, Novfs_fill_super); +- +- DbgPrint( "Novfs_get_sb: sb=0x%x Fstype=0x%x Dev_name=%s\n", sb, Fstype, Dev_name); +- +- return (sb ); +-} +- +-/*++======================================================================*/ +-void Novfs_kill_sb(struct super_block *SB) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- kill_litter_super(SB); +-} +- +-/*++======================================================================*/ +-ssize_t Novfs_Control_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- ssize_t retval=0; +- +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(buf); +- UNUSED_VARIABLE(nbytes); +- UNUSED_VARIABLE(ppos); +- +- DbgPrint( "Novfs_Control_read: kernel_locked 0x%x\n", kernel_locked()); +- +- return retval; +-} +- +-/*++======================================================================*/ +-ssize_t Novfs_Control_write(struct file * file, const char * buf, size_t nbytes, loff_t *ppos) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- ssize_t retval=0; +- +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(buf); +- UNUSED_VARIABLE(nbytes); +- UNUSED_VARIABLE(ppos); +- +- DbgPrint( "Novfs_Control_write: kernel_locked 0x%x\n", kernel_locked()); +- if (buf && nbytes) +- { +- } +- +- return(retval); +-} +- +-/*++======================================================================*/ +-int Novfs_Control_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retval=0; +- +- UNUSED_VARIABLE(inode); +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(cmd); +- UNUSED_VARIABLE(arg); +- +- DbgPrint( "Novfs_Control_ioctl: kernel_locked 0x%x\n", kernel_locked()); +- +- return(retval); +-} +- +-/*++======================================================================*/ +-int __init init_novfs (void) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode; +- +- +- retCode = Init_Procfs_Interface(); +- +- init_profile(); +- +- if ( !retCode ) +- { +- DbgPrint("init_novfs: %s %s %s\n", __DATE__, __TIME__, NOVFS_VERSION_STRING); +- Init_Daemon_Queue(); +- Scope_Init(); +- retCode = register_filesystem(&Novfs_fs_type); +- if ( retCode ) +- { +- Uninit_Procfs_Interface(); +- Uninit_Daemon_Queue(); +- Scope_Uninit(); +- } +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-void __exit exit_novfs(void) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- printk( KERN_INFO "exit_novfs\n"); +- Scope_Uninit(); +- printk( KERN_INFO "exit_novfs after Scope_Uninit\n"); +- Uninit_Daemon_Queue(); +- printk( KERN_INFO "exit_novfs after Uninit_Daemon_Queue\n"); +- Uninit_Procfs_Interface(); +- printk( KERN_INFO "exit_novfs Uninit_Procfs_Interface\n"); +- unregister_filesystem(&Novfs_fs_type); +- printk( KERN_INFO "exit_novfs: Exit\n"); +- if (Novfs_CurrentMount) +- { +- Novfs_Free(Novfs_CurrentMount); +- Novfs_CurrentMount = NULL; +- } +-} +- +-/*++======================================================================*/ +-int Novfs_lock_inode_cache( struct inode *i ) +-/* +- * +- * Arguments: struct inode *i - pointer to directory inode +- * +- * Returns: 0 - locked +- * -1 - not locked +- * +- * Abstract: Locks the inode cache. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- int retVal = 0; +- +- DbgPrint("Novfs_lock_inode_cache: 0x%p\n", i); +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- down( &id->DirCacheLock ); +- retVal = 1; +- } +- DbgPrint("Novfs_lock_inode_cache: return %d\n", retVal); +- return( retVal ); +-} +- +-/*++======================================================================*/ +-void Novfs_unlock_inode_cache( struct inode *i ) +-/* +- * Arguments: struct inode *i - pointer to directory inode +- * +- * Returns: nothing +- * +- * Abstract: Unlocks inode cache. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- up( &id->DirCacheLock ); +- } +-} +- +-/*++======================================================================*/ +-int Novfs_enumerate_inode_cache( struct inode *i, struct list_head **iteration, ino_t *ino, PENTRY_INFO info) +-/* +- * Arguments: struct inode *i - pointer to directory inode +- * +- * Returns: 0 - item found +- * -1 - done +- * +- * Abstract: Unlocks inode cache. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *l=NULL; +- int retVal = -1; +- +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- if ( (NULL == iteration) || (NULL == *iteration) ) +- { +- l = id->DirCache.next; +- } +- else +- { +- l = *iteration; +- } +- +- if (l == &id->DirCache) +- { +- l = NULL; +- } +- else +- { +- dc = list_entry(l, DIR_CACHE, list); +- +- *ino = dc->ino; +- info->type = 0; +- info->mode = dc->mode; +- info->size = dc->size; +- info->atime = dc->atime; +- info->mtime = dc->mtime; +- info->ctime = dc->ctime; +- info->namelength = dc->nameLen; +- memcpy(info->name, dc->name, dc->nameLen); +- info->name[dc->nameLen] = '\0'; +- retVal = 0; +- +- l = l->next; +- } +- } +- *iteration = l; +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Novfs_get_entry( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- int retVal = -1; +- char *n=""; +- int nl=6; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- if (name && name->len) +- { +- n = (char *)name->name; +- nl = name->len; +- } +- DbgPrint("Novfs_get_entry:\n" \ +- " inode: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n", +- i, nl, n, *ino); +- +- dc = Novfs_lookup_inode_cache(i, name, *ino); +- if (dc) +- { +- dc->flags |= ENTRY_VALID; +- retVal = 0; +- *ino = dc->ino; +- info->type = 0; +- info->mode = dc->mode; +- info->size = dc->size; +- info->atime = dc->atime; +- info->mtime = dc->mtime; +- info->ctime = dc->ctime; +- info->namelength = dc->nameLen; +- memcpy(info->name, dc->name, dc->nameLen); +- info->name[dc->nameLen] = '\0'; +- retVal = 0; +- } +- } +- DbgPrint("Novfs_get_entry: return %d\n", retVal); +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Novfs_get_entry_time( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info, u64 *EntryTime) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- int retVal = -1; +- char *n=""; +- int nl=6; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- if (name && name->len) +- { +- n = (char *)name->name; +- nl = name->len; +- } +- DbgPrint("Novfs_get_entry:\n" \ +- " inode: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n", +- i, nl, n, *ino); +- +- dc = Novfs_lookup_inode_cache(i, name, *ino); +- if (dc) +- { +- retVal = 0; +- *ino = dc->ino; +- info->type = 0; +- info->mode = dc->mode; +- info->size = dc->size; +- info->atime = dc->atime; +- info->mtime = dc->mtime; +- info->ctime = dc->ctime; +- info->namelength = dc->nameLen; +- memcpy(info->name, dc->name, dc->nameLen); +- info->name[dc->nameLen] = '\0'; +- if (EntryTime) +- { +- *EntryTime = dc->jiffies; +- } +- retVal = 0; +- } +- } +- DbgPrint("Novfs_get_entry: return %d\n", retVal); +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Novfs_get_remove_entry( struct inode *i, ino_t *ino, PENTRY_INFO info) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: This routine will return the first entry on the list +- * and then remove it. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *l=NULL; +- int retVal = -1; +- +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- l = id->DirCache.next; +- +- if (l != &id->DirCache) +- { +- dc = list_entry(l, DIR_CACHE, list); +- +- *ino = dc->ino; +- info->type = 0; +- info->mode = dc->mode; +- info->size = dc->size; +- info->atime = dc->atime; +- info->mtime = dc->mtime; +- info->ctime = dc->ctime; +- info->namelength = dc->nameLen; +- memcpy(info->name, dc->name, dc->nameLen); +- info->name[dc->nameLen] = '\0'; +- retVal = 0; +- +- list_del( &dc->list ); +- Novfs_Free( dc ); +- DCCount--; +- +- } +- } +- return( retVal ); +-} +- +-/*++======================================================================*/ +-void Novfs_invalidate_inode_cache( struct inode *i ) +-/* +- * Arguments: struct inode *i - pointer to directory inode +- * +- * Returns: nothing +- * +- * Abstract: Marks all entries in the directory cache as invalid. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *l; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- list_for_each(l, &id->DirCache) +- { +- dc = list_entry(l, DIR_CACHE, list); +- dc->flags &= ~ENTRY_VALID; +- } +- } +-} +- +-/*++======================================================================*/ +-PDIR_CACHE Novfs_lookup_inode_cache( struct inode *i, struct qstr *name, ino_t ino ) +-/* +- * Arguments: struct inode *i - pointer to directory inode +- * struct qstr *name - pointer to name +- * ino_t - inode number +- * +- * Returns: DIR_CACHE entry if match +- * NULL - if there is no match. +- * +- * Abstract: Checks a inode directory to see if there are any enties +- * matching name or ino. If name is specified then ino is +- * not used. ino is use if name is not specified. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc, retVal=NULL; +- struct list_head *l; +- char *n=""; +- int nl=6; +- int hash=0; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- if (name && name->name) +- { +- nl = name->len; +- n = (char *)name->name; +- hash = name->hash; +- } +- DbgPrint("Novfs_lookup_inode_cache:\n" \ +- " inode: 0x%p\n" \ +- " name: %.*s\n" \ +- " hash: 0x%x\n" \ +- " len: %d\n" \ +- " ino: %d\n", +- i, nl, n, hash, nl, ino); +- +- list_for_each(l, &id->DirCache) +- { +- dc = list_entry(l, DIR_CACHE, list); +- if (name) +- { +- +-/* DbgPrint("Novfs_lookup_inode_cache: 0x%p\n" \ +- " ino: %d\n" \ +- " hash: 0x%x\n" \ +- " len: %d\n" \ +- " name: %.*s\n", +- dc, dc->ino, dc->hash, dc->nameLen, dc->nameLen, dc->name); +-*/ +- if ( (name->hash == dc->hash) && +- (name->len == dc->nameLen) && +- (0 == memcmp(name->name, dc->name, name->len)) ) +- { +- retVal = dc; +- break; +- } +- } +- else +- { +- if (ino == dc->ino) +- { +- retVal = dc; +- break; +- } +- } +- } +- } +- +- DbgPrint("Novfs_lookup_inode_cache: return 0x%p\n", retVal); +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Novfs_lookup_validate( struct inode *i, struct qstr *name, ino_t ino ) +-/* +- * Arguments: struct inode *i - pointer to directory inode +- * struct qstr *name - pointer to name +- * ino_t - inode number +- * +- * Returns: 0 if found +- * !0 if not found +- * +- * Abstract: Checks a inode directory to see if there are any enties +- * matching name or ino. If entry is found the valid bit +- * is set. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- int retVal = -1; +- char *n=""; +- int nl=6; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- if (name && name->len) +- { +- n = (char *)name->name; +- nl = name->len; +- } +- DbgPrint("Novfs_update_entry:\n" \ +- " inode: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n", +- i, nl, n, ino); +- +- dc = Novfs_lookup_inode_cache( i, name, ino ); +- if (dc) +- { +- dc->flags |= ENTRY_VALID; +- retVal = 0; +- } +- } +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Novfs_add_inode_entry( +- struct inode *i, +- struct qstr *name, +- ino_t ino, +- PENTRY_INFO info) +-/* +- * Arguments: +- * +- * Returns: -ENOMEM - alloc error. +- * 0 - success. +- * +- * Abstract: Added entry to directory cache. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE new; +- int retVal = -ENOMEM; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- new = Novfs_Malloc(sizeof(DIR_CACHE)+name->len, GFP_KERNEL); +- if (new) +- { +- DCCount++; +- DbgPrint("Novfs_add_inode_entry:\n" \ +- " inode: 0x%p\n" \ +- " id: 0x%p\n" \ +- " DC: 0x%p\n" \ +- " new: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n" \ +- " size: %lld\n" \ +- " mode: 0x%x\n", +- i, id, &id->DirCache, new, name->len, name->name, ino, info->size, info->mode); +- +- retVal = 0; +- new->flags = ENTRY_VALID; +- new->jiffies = get_jiffies_64(); +- new->size = info->size; +- new->mode = info->mode; +- new->atime = info->atime; +- new->mtime = info->mtime; +- new->ctime = info->ctime; +- new->ino = ino; +- new->hash = name->hash; +- new->nameLen = name->len; +- memcpy(new->name, name->name, name->len); +- new->name[new->nameLen] = '\0'; +- list_add(&new->list, &id->DirCache); +- +-/* list_for_each(l, &id->DirCache) +- { +- dc = list_entry(l, DIR_CACHE, list); +- if ( dc->hash > new->hash ) +- { +- break; +- } +- } +- +- DbgPrint("Novfs_add_inode_entry: adding 0x%p to 0x%p\n", new, l); +- list_add(&new->list, l); +-*/ +- } +- } +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Novfs_update_entry( struct inode *i, struct qstr *name, ino_t ino, PENTRY_INFO info) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- int retVal = -1; +- char *n=""; +- int nl=6; +- char atime_buf[32]; +- char mtime_buf[32]; +- char ctime_buf[32]; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- +- if (name && name->len) +- { +- n = (char *)name->name; +- nl = name->len; +- } +- ctime_r(&info->atime.tv_sec, atime_buf); +- ctime_r(&info->mtime.tv_sec, mtime_buf); +- ctime_r(&info->ctime.tv_sec, ctime_buf); +- DbgPrint("Novfs_update_entry:\n" \ +- " inode: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n" \ +- " size: %lld\n" \ +- " atime: %s\n" \ +- " mtime: %s\n" \ +- " ctime: %s\n", +- i, nl, n, ino, info->size, atime_buf, mtime_buf, ctime_buf); +- +- +- dc = Novfs_lookup_inode_cache(i, name, ino); +- if (dc) +- { +- retVal = 0; +- dc->flags = ENTRY_VALID; +- dc->jiffies = get_jiffies_64(); +- dc->size = info->size; +- dc->mode = info->mode; +- dc->atime = info->atime; +- dc->mtime = info->mtime; +- dc->ctime = info->ctime; +- +- ctime_r(&dc->atime.tv_sec, atime_buf); +- ctime_r(&dc->mtime.tv_sec, mtime_buf); +- ctime_r(&dc->ctime.tv_sec, ctime_buf); +- DbgPrint("Novfs_update_entry entry: 0x%x\n" \ +- " flags: 0x%x\n" \ +- " jiffies: %lld\n" \ +- " ino: %d\n" \ +- " size: %lld\n" \ +- " mode: 0%o\n" \ +- " atime: %s\n" \ +- " mtime: %s\n" \ +- " ctime: %s\n" \ +- " hash: 0x%x\n" \ +- " nameLen: %d\n" \ +- " name: %s\n", +- dc, dc->flags, dc->jiffies, dc->ino, dc->size, dc->mode, +- atime_buf, mtime_buf, ctime_buf, dc->hash, dc->nameLen, dc->name); +- } +- } +- DbgPrint("Novfs_update_entry: return %d\n", retVal); +- return( retVal ); +-} +- +-/*++======================================================================*/ +-void Novfs_remove_inode_entry( struct inode *i, struct qstr *name, ino_t ino) +-/* +- * Arguments: +- * +- * Returns: nothing +- * +- * Abstract: Removes entry from directory cache. You can specify a name +- * or an inode number. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- char *n=""; +- int nl=6; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- dc = Novfs_lookup_inode_cache( i, name, ino ); +- if (dc) +- { +- if (name && name->name) +- { +- nl = name->len; +- n = (char *)name->name; +- } +- DbgPrint("Novfs_remove_inode_entry:\n" \ +- " inode: 0x%p\n" \ +- " id: 0x%p\n" \ +- " DC: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n" \ +- " entry: 0x%p\n" \ +- " name: %.*s\n"\ +- " ino: %d\n" \ +- " next: 0x%p\n" \ +- " prev: 0x%p\n", +- i, id, &id->DirCache, nl, n, ino, dc, dc->nameLen, dc->name, dc->ino, dc->list.next, dc->list.prev); +- list_del( &dc->list ); +- Novfs_Free( dc ); +- DCCount--; +- +- } +- } +-} +- +-/*++======================================================================*/ +-void Novfs_free_invalid_entries( struct inode *i ) +-/* +- * Arguments: struct inode *i - pointer to directory inode. +- * +- * Returns: nothing +- * +- * Abstract: Frees all invalid entries in the directory cache. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *l; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- list_for_each( l, &id->DirCache ) +- { +- dc = list_entry( l, DIR_CACHE, list ); +- if ( 0 == (dc->flags & ENTRY_VALID) ) +- { +- DbgPrint("Novfs_free_invalid_entries:\n" \ +- " inode: 0x%p\n" \ +- " id: 0x%p\n" \ +- " entry: 0x%p\n" \ +- " name: %.*s\n" \ +- " ino: %d\n", +- i, id, dc, dc->nameLen, dc->name, dc->ino); +- l = l->prev; +- list_del( &dc->list ); +- Novfs_Free( dc ); +- DCCount--; +- } +- } +- } +-} +- +-/*++======================================================================*/ +-void Novfs_free_inode_cache( struct inode *i ) +-/* +- * Arguments: struct inode *i - pointer to directory inode. +- * +- * Returns: nothing +- * +- * Abstract: Frees all entries in the inode cache. +- * +- * Notes: DirCacheLock should be held before calling this routine. +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *l; +- +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) +- { +- list_for_each( l, &id->DirCache ) +- { +- dc = list_entry( l, DIR_CACHE, list ); +- l = l->prev; +- list_del( &dc->list ); +- Novfs_Free( dc ); +- DCCount--; +- } +- } +-} +- +-/*++======================================================================*/ +-int +-NO_TRACE +-Novfs_dump_inode_cache(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-#ifdef CONFIG_KDB +- struct inode *inode=NULL; +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *l; +- char atime_buf[32]; +- char mtime_buf[32]; +- char ctime_buf[32]; +- +- if (Novfs_root) +- { +- inode = Novfs_root->d_inode; +- } +- +- if (argc > 0) +- { +- inode = (void *)simple_strtoul(argv[1], NULL, 0); +- } +- +- kdb_printf("Inode: 0x%p\n", inode); +- if (inode) +- { +- id = inode->u.generic_ip; +- kdb_printf("INODE_DATA: 0x%p\n", id); +- +- if ( id && id->DirCache.next ) +- { +- list_for_each(l, &id->DirCache) +- { +- dc = list_entry(l, DIR_CACHE, list); +- ctime_r(&dc->atime.tv_sec, atime_buf); +- ctime_r(&dc->mtime.tv_sec, mtime_buf); +- ctime_r(&dc->ctime.tv_sec, ctime_buf); +- +- DbgPrint("Cache Entry: 0x%p\n" \ +- " flags: 0x%x\n" \ +- " jiffies: %llu\n" \ +- " ino: %u\n" \ +- " size: %llu\n" \ +- " mode: 0%o\n" \ +- " atime: %s\n" \ +- " mtime: %s\n" \ +- " ctime: %s\n" \ +- " hash: 0x%x\n" \ +- " len: %d\n" \ +- " name: %s\n", +- dc, dc->flags, dc->jiffies, +- dc->ino, dc->size, dc->mode, +- atime_buf, mtime_buf, ctime_buf, +- dc->hash, dc->nameLen, dc->name); +- } +- } +- } +-#endif +- return(0); +-} +- +-/*++======================================================================*/ +-void +-NO_TRACE +-Novfs_dump_inode( void *pf ) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- struct inode *inode; +- void (*pfunc)(char *Fmt, ...) = pf; +- PINODE_DATA id; +- PDIR_CACHE dc; +- struct list_head *il, *l; +- char atime_buf[32]; +- char mtime_buf[32]; +- char ctime_buf[32]; +- unsigned long icnt=0, dccnt=0; +- +- down( &InodeList_lock ); +- list_for_each(il, &InodeList) +- { +- id = list_entry(il, INODE_DATA, IList); +- inode = id->Inode; +- if (inode) +- { +- icnt++; +- +- pfunc("Inode=0x%x I_ino=%d\n", inode, inode->i_ino); +- +- pfunc(" atime=%s\n", ctime_r(&inode->i_atime.tv_sec, atime_buf)); +- pfunc(" ctime=%s\n", ctime_r(&inode->i_mtime.tv_sec, atime_buf)); +- pfunc(" mtime=%s\n", ctime_r(&inode->i_ctime.tv_sec, atime_buf)); +- pfunc(" size=%lld\n", inode->i_size); +- pfunc(" mode=0%o\n", inode->i_mode); +- } +- +- pfunc(" INODE_DATA: 0x%p Name=%s Scope=0x%p\n", id, id->Name, id->Scope); +- +- if (id->DirCache.next ) +- { +- list_for_each(l, &id->DirCache) +- { +- dccnt++; +- dc = list_entry(l, DIR_CACHE, list); +- ctime_r(&dc->atime.tv_sec, atime_buf); +- ctime_r(&dc->mtime.tv_sec, mtime_buf); +- ctime_r(&dc->ctime.tv_sec, ctime_buf); +- +- pfunc(" Cache Entry: 0x%p\n" \ +- " flags: 0x%x\n" \ +- " jiffies: %llu\n" \ +- " ino: %u\n" \ +- " size: %llu\n" \ +- " mode: 0%o\n" \ +- " atime: %s\n" \ +- " mtime: %s\n" \ +- " ctime: %s\n" \ +- " hash: 0x%x\n" \ +- " len: %d\n" \ +- " name: %s\n", +- dc, dc->flags, dc->jiffies, +- dc->ino, dc->size, dc->mode, +- atime_buf, mtime_buf, ctime_buf, +- dc->hash, dc->nameLen, dc->name); +- } +- } +- } +- up( &InodeList_lock ); +- +- pfunc("Inodes: %d(%d) DirCache: %d(%d)\n", InodeCount, icnt, DCCount, dccnt ); +- +-} +- +-module_init(init_novfs) +-module_exit(exit_novfs) +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Novell Inc."); +-MODULE_DESCRIPTION("Novell NetWare Client for Linux"); +-MODULE_VERSION( NOVFS_VERSION_STRING ); +diff -uNr src.old/novfs/m src/novfs/m +--- src.old/novfs/m 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/m 1970-01-01 01:00:00.000000000 +0100 +@@ -1,12 +0,0 @@ +-#!/bin/sh +- +-VERSION=`uname -r` +- +-make -C /usr/src/linux SUBDIRS=$PWD modules +- +-if [ -e novfs.ko ] +-then +- mkdir -p -m 755 /lib/modules/$VERSION/kernel/fs/novfs +- echo "copying novfs.ko to /lib/modules/$VERSION/kernel/fs/novfs" +- cp novfs.ko /lib/modules/$VERSION/kernel/fs/novfs +-fi +diff -uNr src.old/novfs/mk_novfs src/novfs/mk_novfs +--- src.old/novfs/mk_novfs 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/mk_novfs 1970-01-01 01:00:00.000000000 +0100 +@@ -1,113 +0,0 @@ +-#!/bin/sh +- +-RVAL=1 +-TO_BUILD=1 +- +-BUILD_TYPE=modules +- +-if [ $1 ] +-then +- if [ "$1" = "force" ] +- then +- FORCE=1 +- else +- BUILD_TYPE=$1 +- FORCE=0 +- fi +-else +- FORCE=0 +-fi +- +- +-if [ -d /usr/src/linux-obj/i386 ] +-then +- for i in $(ls /usr/src/linux-obj/i386) +- do +- TO_BUILD=1 +- VERSION=`cat /usr/src/linux-obj/i386/$i/include/linux/version.h |grep UTS_RELEASE |awk '{printf("%s\n", substr($3, 2,length($3)-2))}'` +- NOVFS_PATH=/lib/modules/$VERSION/kernel/fs/novfs +- +- if [ -e /lib/modules/$VERSION/extra/novfs.ko ] +- then +- NOVFS_PATH=/lib/modules/$VERSION/extra +- +- else +- if [ -e /lib/modules/$VERSION/updates/novfs.ko ] +- then +- NOVFS_PATH=/lib/modules/$VERSION/updates +- +- fi +- fi +- +- if [ -d /lib/modules/$VERSION ] +- then +- +- if [ -e $NOVFS_PATH/novfs.ko ] +- then +- CUR_NOVFS_VERSION=`od --strings=8 $NOVFS_PATH/novfs.ko |grep version= |awk '{split($2,a,"="); if("version"==a[1]) printf("%s", a[2])}'` +- CUR_NOVFS_VFS_MAJOR=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"."); printf("%d", a[1])}'` +- CUR_NOVFS_VFS_MINOR=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"."); printf("%d", a[2])}'` +- CUR_NOVFS_VFS_SUB=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"."); printf("%d", a[3])}'` +- CUR_NOVFS_VFS_RELEASE=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"-"); printf("%d", a[2])}'` +- +- NOVFS_VFS_MAJOR=`cat Makefile |grep 'NOVFS_VFS_MAJOR =' |awk '{printf("%d", $3)}'` +- NOVFS_VFS_MINOR=`cat Makefile |grep 'NOVFS_VFS_MINOR =' |awk '{printf("%d", $3)}'` +- NOVFS_VFS_SUB=`cat Makefile |grep 'NOVFS_VFS_SUB =' |awk '{printf("%d", $3)}'` +- NOVFS_VFS_RELEASE=`cat Makefile |grep 'NOVFS_VFS_RELEASE =' |awk '{printf("%d", $3)}'` +- NOVFS_VFS_VERSION="$NOVFS_VFS_MAJOR.$NOVFS_VFS_MINOR.$NOVFS_VFS_SUB-$NOVFS_VFS_RELEASE" +- +- TO_BUILD=0 +- +- if [ $NOVFS_VFS_MAJOR -gt $CUR_NOVFS_VFS_MAJOR ] +- then +- TO_BUILD=1 +- else +- if [ $NOVFS_VFS_MAJOR -eq $CUR_NOVFS_VFS_MAJOR ] +- then +- if [ $NOVFS_VFS_MINOR -gt $CUR_NOVFS_VFS_MINOR ] +- then +- TO_BUILD=1 +- else +- if [ $NOVFS_VFS_MINOR -eq $CUR_NOVFS_VFS_MINOR ] +- then +- if [ $NOVFS_VFS_SUB -gt $CUR_NOVFS_VFS_SUB ] +- then +- TO_BUILD=1 +- else +- if [ $NOVFS_VFS_SUB -eq $CUR_NOVFS_VFS_SUB ] +- then +- if [ $NOVFS_VFS_RELEASE -gt $CUR_NOVFS_VFS_RELEASE ] +- then +- TO_BUILD=1 +- fi +- fi +- fi +- fi +- fi +- fi +- fi +- fi +- +- if [ $FORCE -eq 1 ] +- then +- TO_BUILD=1; +- fi +- +- if [ $TO_BUILD -eq 1 ] +- then +- echo Building novfs.ko for $VERSION +- make -C /usr/src/linux-obj/i386/$i SUBDIRS=$PWD $BUILD_TYPE +- RVAL=$? +- if [ -e novfs.ko ] +- then +- mkdir -p -m 755 $NOVFS_PATH +- echo "copying novfs.ko to $NOVFS_PATH" +- cp novfs.ko $NOVFS_PATH +- RVAL=$? +- fi +- fi +- fi +- done +-fi +-exit $RVAL +- +diff -uNr src.old/novfs/nwcapi.c src/novfs/nwcapi.c +--- src.old/novfs/nwcapi.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/nwcapi.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,2410 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: nwcapi.c +- * Version: v1.00 +- * Author: James Turner/Richard Williams +- * +- * Abstract: This module contains functions used to interface to +- * the library interface of the daemon. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +- +-/*===[ Include files specific to this module ]============================*/ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "nwcapi.h" +-#include "nwerror.h" +-#include "commands.h" +- +-#include "vfs.h" +- +-/*===[ External data ]====================================================*/ +- +-/*===[ External prototypes ]==============================================*/ +- +-extern int DbgPrint( char *Fmt, ... ); +-extern void mydump(int size, void *dumpptr); +- +-extern session_t Scope_Get_SessionId( void *Scope ); +-extern int Queue_Daemon_Command(void *request, u_long reqlen, void *data, int dlen, void **reply, u_long *replen, int interruptible); +- +-extern int do_login(NclString *Server, NclString *Username, NclString *Password, u_long *lgnId, session_t Session); +- +-void GetUserData(NwcScanConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply); +-void GetConnData(NwcGetConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply); +- +-/*===[ Manifest constants ]===============================================*/ +- +-/*===[ Type definitions ]=================================================*/ +- +-/*===[ Function prototypes ]==============================================*/ +- +-/*===[ Global variables ]=================================================*/ +- +-/*===[ Code ]=============================================================*/ +- +-/*++======================================================================*/ +- +-/*++======================================================================*/ +-int NwOpenConnByName(PXPLAT pdata, u_long *Handle, session_t Session) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCOpenConnByName openConn, connReply; +-NwcOpenConnByName ocbn; +-u_long retCode = 0, cmdlen, datalen, replylen, cpylen; +-char *data; +- +- cpylen = copy_from_user(&ocbn, pdata->reqData, sizeof(ocbn)); +- datalen = sizeof(*openConn) + strlen_user(ocbn.pName->pString) + strlen_user(ocbn.pServiceType); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_OPEN_CONN_BY_NAME; +- +- cmd->dataLen = datalen; +- openConn = (PNwdCOpenConnByName)cmd->data; +- +- openConn->nameLen = strlen_user(ocbn.pName->pString); +- openConn->serviceLen = strlen_user(ocbn.pServiceType); +- openConn->uConnFlags = ocbn.uConnFlags; +- openConn->ConnHandle = ocbn.ConnHandle; +- data = (char *)openConn; +- data += sizeof(*openConn); +- openConn->oName = sizeof(*openConn); +- +- openConn->oServiceType = openConn->oName + openConn->nameLen; +- cpylen = copy_from_user(data, ocbn.pName->pString, openConn->nameLen); +- data += openConn->nameLen; +- cpylen = copy_from_user(data, ocbn.pServiceType, openConn->serviceLen); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- /* +- * we got reply data from the daemon +- */ +- connReply = (PNwdCOpenConnByName)reply->data; +- retCode = reply->Reply.ErrorCode; +- if (!retCode) +- { +- /* +- * we got valid data. +- */ +- connReply = (PNwdCOpenConnByName)reply->data; +- ocbn.RetConnHandle = connReply->newConnHandle; +- *Handle = connReply->newConnHandle; +- cpylen = copy_to_user(pdata->reqData, &ocbn, sizeof(ocbn)); +- DbgPrint("New Conn Handle = %X\n", connReply->newConnHandle); +- } +- Novfs_Free(reply); +- } +- +- Novfs_Free(cmd); +- } +- +- return((int)retCode); +- +-} +- +-/*++======================================================================*/ +-int NwOpenConnByAddr(PXPLAT pdata, u_long *Handle, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCOpenConnByAddr openConn, connReply; +-NwcOpenConnByAddr ocba; +-NwcTranAddr tranAddr; +-u_long retCode = 0, cmdlen, datalen, replylen, cpylen; +-char addr[MAX_ADDRESS_LENGTH]; +- +- cpylen = copy_from_user(&ocba, pdata->reqData, sizeof(ocba)); +- datalen = sizeof(*openConn); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_OPEN_CONN_BY_ADDRESS; +- cmd->dataLen = datalen; +- openConn = (PNwdCOpenConnByAddr)cmd->data; +- +- cpylen = copy_from_user(&tranAddr, ocba.pTranAddr, sizeof(tranAddr)); +- +- DbgPrint("NwOpenConnByAddr: tranAddr\n"); +- mydump(sizeof(tranAddr), &tranAddr); +- +- openConn->TranAddr.uTransportType = tranAddr.uTransportType; +- openConn->TranAddr.uAddressLength = tranAddr.uAddressLength; +- memset(addr, 0xcc, sizeof(addr)-1); +- +- cpylen = copy_from_user(addr, tranAddr.puAddress, tranAddr.uAddressLength); +- +- DbgPrint("NwOpenConnByAddr: addr\n"); +- mydump(sizeof(addr), addr); +- +- openConn->TranAddr.oAddress = *(u_long *)(&addr[2]); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- /* +- * we got reply data from the daemon +- */ +- connReply = (PNwdCOpenConnByAddr)reply->data; +- retCode = reply->Reply.ErrorCode; +- if (!retCode) +- { +- /* +- * we got valid data. +- */ +- connReply = (PNwdCOpenConnByAddr)reply->data; +- ocba.ConnHandle = connReply->ConnHandle; +- *Handle = connReply->ConnHandle; +- cpylen = copy_to_user(pdata->reqData, &ocba, sizeof(ocba)); +- DbgPrint("New Conn Handle = %X\n", connReply->ConnHandle); +- } +- Novfs_Free(reply); +- } +- +- Novfs_Free(cmd); +- } +- +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwOpenConnByRef(PXPLAT pdata, u_long *Handle, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCOpenConnByRef openConn; +-NwcOpenConnByReference ocbr; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- +- cpylen = copy_from_user(&ocbr, pdata->reqData, sizeof(ocbr)); +- datalen = sizeof(*openConn); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_OPEN_CONN_BY_REFERENCE; +- cmd->dataLen = datalen; +- openConn = (PNwdCOpenConnByRef)cmd->data; +- +- memcpy(openConn, &ocbr, sizeof(ocbr)); +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- /* +- * we got reply data from the daemon +- */ +- openConn = (PNwdCOpenConnByRef)reply->data; +- retCode = reply->Reply.ErrorCode; +- if (!retCode) +- { +- /* +- * we got valid data. +- */ +- ocbr.ConnHandle = openConn->ConnHandle; +- *Handle = openConn->ConnHandle; +- +- cpylen = copy_to_user(pdata->reqData, &ocbr, sizeof(ocbr)); +- DbgPrint("New Conn Handle = %X\n", openConn->ConnHandle); +- } +- Novfs_Free(reply); +- } +- +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwRawSend(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-NwcRequest xRequest; +-PNwcFrag frag, cFrag, reqFrag; +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +-u_long x, totalLen; +-PNwdCNCPReq ncpData; +-PNwdCNCPRep ncpReply; +-u_char *reqData; +-unsigned long actualReplyLength=0; +- +- DbgPrint("[XPLAT] Process Raw NCP Send\n"); +- cpylen = copy_from_user(&xRequest, pdata->reqData, sizeof(xRequest)); +- +- /* +- * Figure out the length of the request +- */ +- frag = Novfs_Malloc(xRequest.uNumReplyFrags * sizeof(NwcFrag), GFP_KERNEL); +- +- DbgPrint("[XPLAT RawNCP] - Reply Frag Count 0x%X\n", xRequest.uNumReplyFrags); +- +- if (!frag) +- return(retCode); +- +- cpylen = copy_from_user(frag, xRequest.pReplyFrags, xRequest.uNumReplyFrags * sizeof(NwcFrag)); +- totalLen = 0; +- +- cFrag = frag; +- for (x = 0; x < xRequest.uNumReplyFrags; x ++) +- { +- DbgPrint("[XPLAT - RawNCP] - Frag Len = %d\n", cFrag->uLength); +- totalLen += cFrag->uLength; +- cFrag++; +- } +- +- +- DbgPrint("[XPLAT - RawNCP] - totalLen = %d\n", totalLen); +- datalen = 0; +- reqFrag = Novfs_Malloc(xRequest.uNumRequestFrags * sizeof(NwcFrag), GFP_KERNEL); +- if (!reqFrag) +- { +- Novfs_Free(frag); +- return(retCode); +- } +- +- cpylen = copy_from_user(reqFrag, xRequest.pRequestFrags, xRequest.uNumRequestFrags * sizeof(NwcFrag)); +- cFrag = reqFrag; +- for (x = 0; x < xRequest.uNumRequestFrags; x ++) +- { +- datalen += cFrag->uLength; +- cFrag++; +- } +- +- /* +- * Allocate the cmd Request +- */ +- cmdlen = datalen + sizeof(*cmd) + sizeof(*ncpData); +- DbgPrint("[XPLAT RawNCP] - Frag Count 0x%X\n", xRequest.uNumRequestFrags); +- DbgPrint("[XPLAT RawNCP] - Total Command Data Len = %x\n", cmdlen); +- +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_RAW_NCP_REQUEST; +- +- /* +- * build the NCP Request +- */ +- cmd->dataLen = cmdlen - sizeof(*cmd); +- ncpData = (PNwdCNCPReq)cmd->data; +- ncpData->replyLen = totalLen; +- ncpData->requestLen = datalen; +- ncpData->ConnHandle = xRequest.ConnHandle; +- ncpData->function = xRequest.uFunction; +- +- +- reqData = ncpData->data; +- cFrag = reqFrag; +- +- for (x = 0; x < xRequest.uNumRequestFrags; x ++) +- { +- cpylen = copy_from_user(reqData, cFrag->pData, cFrag->uLength); +- reqData += cFrag->uLength; +- cFrag++; +- } +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- DbgPrint("RawNCP - reply = %x\n", reply); +- DbgPrint("RawNCP - retCode = %x\n", retCode); +- +- if (reply) +- { +- /* +- * we got reply data from the daemon +- */ +- ncpReply = (PNwdCNCPRep)reply->data; +- retCode = reply->Reply.ErrorCode; +- +- DbgPrint("RawNCP - Reply Frag Count 0x%X\n", xRequest.uNumReplyFrags); +- +- /* +- * We need to copy the reply frags to the packet. +- */ +- reqData = ncpReply->data; +- cFrag = frag; +- +- totalLen = ncpReply->replyLen; +- for (x = 0; x < xRequest.uNumReplyFrags; x ++) +- { +- +- DbgPrint("RawNCP - Copy Frag %d: 0x%X\n", x, cFrag->uLength); +- +- datalen = min(cFrag->uLength, totalLen); +- +- cpylen = copy_to_user(cFrag->pData, reqData, datalen); +- totalLen -= datalen; +- reqData += datalen; +- actualReplyLength += datalen; +- +- cFrag++; +- } +- +- Novfs_Free(reply); +- } +- else +- { +- retCode = -EIO; +- } +- +- Novfs_Free(cmd); +- } +- xRequest.uActualReplyLength = actualReplyLength; +- cpylen = copy_to_user(pdata->reqData, &xRequest, sizeof(xRequest)); +- +- Novfs_Free(reqFrag); +- Novfs_Free(frag); +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-int NwConnClose(PXPLAT pdata, u_long *Handle, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcCloseConn cc; +-PNwdCCloseConn nwdClose; +-u_long retCode = 0, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&cc, pdata->reqData, sizeof(cc)); +- +- datalen = sizeof(*nwdClose); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_CLOSE_CONN; +- +- nwdClose = (PNwdCCloseConn)cmd->data; +- cmd->dataLen = sizeof(*nwdClose); +- nwdClose->ConnHandle = cc.ConnHandle; +- *Handle = cc.ConnHandle; +- +- /* +- * send the request +- */ +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, 0); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- +- } +- +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwSysConnClose(PXPLAT pdata, u_long *Handle, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcCloseConn cc; +-PNwdCCloseConn nwdClose; +-u_long retCode = 0, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&cc, pdata->reqData, sizeof(cc)); +- +- datalen = sizeof(*nwdClose); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SYS_CLOSE_CONN; +- +- nwdClose = (PNwdCCloseConn)cmd->data; +- cmd->dataLen = sizeof(*nwdClose); +- nwdClose->ConnHandle = cc.ConnHandle; +- *Handle = cc.ConnHandle; +- +- /* +- * send the request +- */ +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, 0); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- +- } +- +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwLoginIdentity(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-NwcLoginIdentity lgn, *plgn; +-int retCode = -ENOMEM; +-NclString server; +-NclString username; +-NclString password; +-u_long cpylen; +-NwcString nwcStr; +- +- cpylen = copy_from_user(&lgn, pdata->reqData, sizeof(lgn)); +- +- DbgPrint("NwLoginIdentity:\n"); +- mydump(sizeof(lgn), &lgn); +- +- +- +- cpylen = copy_from_user(&nwcStr, lgn.pDomainName, sizeof(nwcStr)); +- DbgPrint("NwLoginIdentity: DomainName\n"); +- mydump(sizeof(nwcStr), &nwcStr); +- +- if ( (server.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL)) ) +- { +- server.type = nwcStr.DataType; +- server.len = nwcStr.DataLen; +- if ( !copy_from_user((void *)server.buffer, nwcStr.pBuffer, server.len) ) +- { +- DbgPrint("NwLoginIdentity: Server\n"); +- mydump(server.len, server.buffer); +- +- cpylen = copy_from_user(&nwcStr, lgn.pObjectName, sizeof(nwcStr)); +- DbgPrint("NwLoginIdentity: ObjectName\n"); +- mydump(sizeof(nwcStr), &nwcStr); +- +- if ( (username.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL)) ) +- { +- username.type = nwcStr.DataType; +- username.len = nwcStr.DataLen; +- if ( !copy_from_user((void *)username.buffer, nwcStr.pBuffer, username.len) ) +- { +- DbgPrint("NwLoginIdentity: User\n"); +- mydump(username.len, username.buffer); +- +- cpylen = copy_from_user(&nwcStr, lgn.pPassword, sizeof(nwcStr)); +- DbgPrint("NwLoginIdentity: Password\n"); +- mydump(sizeof(nwcStr), &nwcStr); +- +- if ( (password.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL)) ) +- { +- password.type = nwcStr.DataType; +- password.len = nwcStr.DataLen; +- if ( !copy_from_user((void *)password.buffer, nwcStr.pBuffer, password.len) ) +- { +- retCode = do_login(&server, &username, &password, (u_long *)&lgn.AuthenticationId, Session); +- if (retCode) +- { +- lgn.AuthenticationId = 0; +- } +- +- plgn = (NwcLoginIdentity *)pdata->reqData; +- cpylen = copy_to_user(&plgn->AuthenticationId, &lgn.AuthenticationId, sizeof(plgn->AuthenticationId)); +- +- } +- memset(password.buffer, 0, password.len); +- Novfs_Free(password.buffer); +- } +- } +- memset(username.buffer, 0, username.len); +- Novfs_Free(username.buffer); +- } +- } +- Novfs_Free(server.buffer); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int NwAuthConnWithId(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-NwcAuthenticateWithId pauth; +-PNwdCAuthenticateWithId pDauth; +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- datalen = sizeof(*pDauth); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_AUTHENTICATE_CONN_WITH_ID; +- +- +- cpylen = copy_from_user(&pauth, pdata->reqData, sizeof(pauth)); +- +- pDauth = (PNwdCAuthenticateWithId)cmd->data; +- cmd->dataLen = datalen; +- pDauth->AuthenticationId = pauth.AuthenticationId; +- pDauth->ConnHandle = pauth.ConnHandle; +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int NwLicenseConn(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcLicenseConn lisc; +-PNwdCLicenseConn pDLisc; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- datalen = sizeof(*pDLisc); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_LICENSE_CONN; +- +- +- cpylen = copy_from_user(&lisc, pdata->reqData, sizeof(lisc)); +- +- pDLisc = (PNwdCLicenseConn)cmd->data; +- cmd->dataLen = datalen; +- pDLisc->ConnHandle = lisc.ConnHandle; +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +-} +- +- +-/*++======================================================================*/ +-int NwLogoutIdentity(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcLogoutIdentity logout; +-PNwdCLogoutIdentity pDLogout; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- datalen = sizeof(*pDLogout); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_LOGOUT_IDENTITY; +- +- cpylen = copy_from_user(&logout, pdata->reqData, sizeof(logout)); +- +- pDLogout = (PNwdCLogoutIdentity)cmd->data; +- cmd->dataLen = datalen; +- pDLogout->AuthenticationId = logout.AuthenticationId; +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-int NwUnlicenseConn(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCUnlicenseConn pUconn; +-NwcUnlicenseConn ulc; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- +- cpylen = copy_from_user(&ulc, pdata->reqData, sizeof(ulc)); +- datalen = sizeof(*pUconn); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_UNLICENSE_CONN; +- cmd->dataLen = datalen; +- pUconn = (PNwdCUnlicenseConn)cmd->data; +- +- pUconn->ConnHandle = ulc.ConnHandle; +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- /* +- * we got reply data from the daemon +- */ +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +- +-/*++======================================================================*/ +-int NwUnAuthenticate(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcUnauthenticate auth; +-PNwdCUnauthenticate pDAuth; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- datalen = sizeof(*pDAuth); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_UNAUTHENTICATE_CONN; +- +- cpylen = copy_from_user(&auth, pdata->reqData, sizeof(auth)); +- +- pDAuth = (PNwdCUnauthenticate)cmd->data; +- cmd->dataLen = datalen; +- pDAuth->AuthenticationId = auth.AuthenticationId; +- pDAuth->ConnHandle = auth.ConnHandle; +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +- +-/*++======================================================================*/ +-int NwGetConnInfo(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcGetConnInfo connInfo; +-PNwdCGetConnInfo pDConnInfo; +-u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; +- +- cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- cpylen = copy_from_user(&connInfo, pdata->reqData, sizeof(NwcGetConnInfo)); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_GET_CONN_INFO; +- +- pDConnInfo = (PNwdCGetConnInfo)cmd->data; +- +- pDConnInfo->ConnHandle = connInfo.ConnHandle; +- pDConnInfo->uInfoLevel = connInfo.uInfoLevel; +- pDConnInfo->uInfoLength = connInfo.uInfoLength; +- cmd->dataLen = sizeof(*pDConnInfo); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- GetConnData(&connInfo, cmd, reply); +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- +- } +- +- return(retCode); +- +-} +- +- +-/*++======================================================================*/ +-int NwSetConnInfo(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcSetConnInfo connInfo; +-PNwdCSetConnInfo pDConnInfo; +-u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; +- +- cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- cpylen = copy_from_user(&connInfo, pdata->reqData, sizeof(NwcSetConnInfo)); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SET_CONN_INFO; +- +- pDConnInfo = (PNwdCSetConnInfo)cmd->data; +- +- pDConnInfo->ConnHandle = connInfo.ConnHandle; +- pDConnInfo->uInfoLevel = connInfo.uInfoLevel; +- pDConnInfo->uInfoLength = connInfo.uInfoLength; +- cmd->dataLen = sizeof(*pDConnInfo); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- +- } +- +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwGetIdentityInfo(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcGetIdentityInfo qidInfo, *gId; +-PNwdCGetIdentityInfo idInfo; +-NwcString xferStr; +-char *str; +-u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; +- +- cmdlen = sizeof(*cmd) + sizeof(*idInfo); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- cpylen = copy_from_user(&qidInfo, pdata->reqData, sizeof(qidInfo)); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_GET_IDENTITY_INFO; +- +- idInfo = (PNwdCGetIdentityInfo)cmd->data; +- +- idInfo->AuthenticationId = qidInfo.AuthenticationId; +- cmd->dataLen = sizeof(*idInfo); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- +- if (!reply->Reply.ErrorCode) +- { +- /* +- * Save the return info to the user structure. +- */ +- gId = pdata->reqData; +- idInfo = (PNwdCGetIdentityInfo)reply->data; +- cpylen = copy_to_user(&gId->AuthenticationId, &idInfo->AuthenticationId, sizeof(idInfo->AuthenticationId)); +- cpylen = copy_to_user(&gId->AuthType, &idInfo->AuthType, sizeof(idInfo->AuthType)); +- cpylen = copy_to_user(&gId->IdentityFlags, &idInfo->IdentityFlags, sizeof(idInfo->IdentityFlags)); +- cpylen = copy_to_user(&gId->NameType, &idInfo->NameType, sizeof(idInfo->NameType)); +- cpylen = copy_to_user(&gId->ObjectType, &idInfo->ObjectType, sizeof(idInfo->ObjectType)); +- +- cpylen = copy_from_user(&xferStr, gId->pDomainName, sizeof(NwcString)); +- str = (char *)((char *)reply->data + idInfo->pDomainNameOffset); +- cpylen = copy_to_user(xferStr.pBuffer, str, idInfo->domainLen); +- xferStr.DataType = NWC_STRING_TYPE_ASCII; +- xferStr.DataLen = idInfo->domainLen; +- cpylen = copy_to_user(gId->pDomainName, &xferStr, sizeof(NwcString)); +- +- +- cpylen = copy_from_user(&xferStr, gId->pObjectName, sizeof(NwcString)); +- str = (char *)((char *)reply->data + idInfo->pObjectNameOffset); +- cpylen = copy_to_user(xferStr.pBuffer, str, idInfo->objectLen); +- xferStr.DataLen = idInfo->objectLen - 1; +- xferStr.DataType = NWC_STRING_TYPE_ASCII; +- cpylen = copy_to_user(gId->pObjectName, &xferStr, sizeof(NwcString)); +- } +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- +- } +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-int NwScanConnInfo(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcScanConnInfo connInfo, *rInfo; +-PNwdCScanConnInfo pDConnInfo; +-u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; +-u_char *localData; +- +- cpylen = copy_from_user(&connInfo, pdata->reqData, sizeof(NwcScanConnInfo)); +- +- cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo) + connInfo.uScanInfoLen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SCAN_CONN_INFO; +- +- pDConnInfo = (PNwdCScanConnInfo)cmd->data; +- +- DbgPrint("NwScanConnInfo: Input Data\n"); +- DbgPrint("connInfo.uScanIndex = 0x%X\n", connInfo.uScanIndex); +- DbgPrint("connInfo.uConnectionReference = 0x%X\n", connInfo.uConnectionReference); +- DbgPrint("connInfo.uScanInfoLevel = 0x%X\n", connInfo.uScanInfoLevel); +- DbgPrint("connInfo.uScanInfoLen = 0x%X\n", connInfo.uScanInfoLen); +- DbgPrint("connInfo.uReturnInfoLength = 0x%X\n", connInfo.uReturnInfoLength); +- DbgPrint("connInfo.uReturnInfoLevel = 0x%X\n", connInfo.uReturnInfoLevel); +- DbgPrint("connInfo.uScanFlags = 0x%X\n", connInfo.uScanFlags); +- +- +- pDConnInfo->uScanIndex = connInfo.uScanIndex; +- pDConnInfo->uConnectionReference = connInfo.uConnectionReference; +- pDConnInfo->uScanInfoLevel = connInfo.uScanInfoLevel; +- pDConnInfo->uScanInfoLen = connInfo.uScanInfoLen; +- pDConnInfo->uReturnInfoLength = connInfo.uReturnInfoLength; +- pDConnInfo->uReturnInfoLevel = connInfo.uReturnInfoLevel; +- pDConnInfo->uScanFlags = connInfo.uScanFlags; +- +- if (pDConnInfo->uScanInfoLen) +- { +- localData = (u_char *)pDConnInfo; +- pDConnInfo->uScanConnInfoOffset = sizeof(*pDConnInfo); +- localData += pDConnInfo->uScanConnInfoOffset; +- cpylen = copy_from_user(localData, connInfo.pScanConnInfo, connInfo.uScanInfoLen); +- } +- else +- { +- pDConnInfo->uScanConnInfoOffset = 0; +- } +- +- +- cmd->dataLen = sizeof(*pDConnInfo); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- DbgPrint("NwScanConnInfo: Reply recieved\n"); +- DbgPrint(" NextIndex = %x\n", connInfo.uScanIndex); +- DbgPrint(" ErrorCode = %x\n", reply->Reply.ErrorCode); +- DbgPrint(" data = %x\n", reply->data); +- +- pDConnInfo = (PNwdCScanConnInfo)reply->data; +- retCode = (u_long)reply->Reply.ErrorCode; +- if (!retCode) +- { +- GetUserData(&connInfo, cmd, reply); +- rInfo = (NwcScanConnInfo *)pdata->repData; +- cpylen = copy_to_user(pdata->repData, &pDConnInfo->uScanIndex, sizeof(pDConnInfo->uScanIndex)); +- cpylen = copy_to_user(&rInfo->uConnectionReference, &pDConnInfo->uConnectionReference, sizeof(pDConnInfo->uConnectionReference)); +- } +- else +- { +- u_long x; +- +- x = 0; +- rInfo = (NwcScanConnInfo *)pdata->reqData; +- cpylen = copy_to_user(&rInfo->uConnectionReference, &x, sizeof(rInfo->uConnectionReference)); +- } +- +- Novfs_Free(reply); +- } +- else +- { +- retCode = -EIO; +- } +- Novfs_Free(cmd); +- +- } +- +- return(retCode); +-} +- +-/*++======================================================================*/ +-void GetUserData(NwcScanConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply) +-/* +- * Abstract: Copies the user data out of the scan conn info call. +- * +- *========================================================================*/ +- +-{ +-u_long uLevel; +-PNwdCScanConnInfo pDConnInfo; +- +-u_char *srcData = NULL; +-u_long dataLen = 0, cpylen; +- +- +- pDConnInfo = (PNwdCScanConnInfo)reply->data; +- uLevel = pDConnInfo->uReturnInfoLevel; +- DbgPrint("[GetUserData] uLevel = %d, reply = 0x%X, reply->data = 0x%X\n", uLevel, reply, reply->data); +- +- switch(uLevel) +- { +- case NWC_CONN_INFO_RETURN_ALL: +- case NWC_CONN_INFO_TRAN_ADDR: +- case NWC_CONN_INFO_NDS_STATE: +- case NWC_CONN_INFO_MAX_PACKET_SIZE: +- case NWC_CONN_INFO_LICENSE_STATE: +- case NWC_CONN_INFO_PUBLIC_STATE: +- case NWC_CONN_INFO_SERVICE_TYPE: +- case NWC_CONN_INFO_DISTANCE: +- case NWC_CONN_INFO_SERVER_VERSION: +- case NWC_CONN_INFO_AUTH_ID: +- case NWC_CONN_INFO_SUSPENDED: +- case NWC_CONN_INFO_WORKGROUP_ID: +- case NWC_CONN_INFO_SECURITY_STATE: +- case NWC_CONN_INFO_CONN_NUMBER: +- case NWC_CONN_INFO_USER_ID: +- case NWC_CONN_INFO_BCAST_STATE: +- case NWC_CONN_INFO_CONN_REF: +- case NWC_CONN_INFO_AUTH_STATE: +- case NWC_CONN_INFO_TREE_NAME: +- case NWC_CONN_INFO_SERVER_NAME: +- case NWC_CONN_INFO_VERSION: +- srcData = (u_char *)pDConnInfo; +- srcData += pDConnInfo->uReturnConnInfoOffset; +- dataLen = pDConnInfo->uReturnInfoLength; +- break; +- +- case NWC_CONN_INFO_RETURN_NONE: +- case NWC_CONN_INFO_TREE_NAME_UNICODE: +- case NWC_CONN_INFO_SERVER_NAME_UNICODE: +- case NWC_CONN_INFO_LOCAL_TRAN_ADDR: +- case NWC_CONN_INFO_ALTERNATE_ADDR: +- case NWC_CONN_INFO_SERVER_GUID: +- default: +- break; +- } +- +- if (srcData && dataLen) +- { +- DbgPrint("Copy Data in GetUserData 0x%X -> 0x%X :: 0x%X\n", +- srcData, connInfo->pReturnConnInfo, dataLen); +- cpylen = copy_to_user(connInfo->pReturnConnInfo, srcData, dataLen); +- } +- +- return; +-} +- +-/*++======================================================================*/ +-void GetConnData(NwcGetConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply) +-/* +- * Abstract: Copies the user data out of the scan conn info call. +- * +- *========================================================================*/ +- +-{ +-u_long uLevel; +-PNwdCGetConnInfo pDConnInfo; +- +-u_char *srcData = NULL; +-u_long dataLen = 0, cpylen; +- +- +- pDConnInfo = (PNwdCGetConnInfo)cmd->data; +- uLevel = pDConnInfo->uInfoLevel; +- +- switch(uLevel) +- { +- case NWC_CONN_INFO_RETURN_ALL: +- srcData = (u_char *)reply->data; +- dataLen = reply->dataLen; +- break; +- +- case NWC_CONN_INFO_RETURN_NONE: +- dataLen = 0; +- break; +- +- case NWC_CONN_INFO_TRAN_ADDR: +- { +- u_char *dstData = connInfo->pConnInfo; +- NwcTranAddr tranAddr; +- +- srcData = (u_char *)reply->data; +- +- cpylen = copy_from_user(&tranAddr, dstData, sizeof(tranAddr)); +- tranAddr.uTransportType = ((PNwdTranAddr)srcData)->uTransportType; +- tranAddr.uAddressLength = ((PNwdTranAddr)srcData)->uAddressLength; +- cpylen = copy_to_user(dstData, &tranAddr, sizeof(tranAddr)); +- cpylen = copy_to_user(tranAddr.puAddress, ((PNwdTranAddr)srcData)->Buffer, ((PNwdTranAddr)srcData)->uAddressLength); +- dataLen=0; +- break; +- } +- case NWC_CONN_INFO_NDS_STATE: +- case NWC_CONN_INFO_MAX_PACKET_SIZE: +- case NWC_CONN_INFO_LICENSE_STATE: +- case NWC_CONN_INFO_PUBLIC_STATE: +- case NWC_CONN_INFO_SERVICE_TYPE: +- case NWC_CONN_INFO_DISTANCE: +- case NWC_CONN_INFO_SERVER_VERSION: +- case NWC_CONN_INFO_AUTH_ID: +- case NWC_CONN_INFO_SUSPENDED: +- case NWC_CONN_INFO_WORKGROUP_ID: +- case NWC_CONN_INFO_SECURITY_STATE: +- case NWC_CONN_INFO_CONN_NUMBER: +- case NWC_CONN_INFO_USER_ID: +- case NWC_CONN_INFO_BCAST_STATE: +- case NWC_CONN_INFO_CONN_REF: +- case NWC_CONN_INFO_AUTH_STATE: +- case NWC_CONN_INFO_VERSION: +- case NWC_CONN_INFO_SERVER_NAME: +- case NWC_CONN_INFO_TREE_NAME: +- srcData = (u_char *)reply->data; +- dataLen = reply->dataLen; +- break; +- +- case NWC_CONN_INFO_TREE_NAME_UNICODE: +- case NWC_CONN_INFO_SERVER_NAME_UNICODE: +- break; +- +- case NWC_CONN_INFO_LOCAL_TRAN_ADDR: +- break; +- +- case NWC_CONN_INFO_ALTERNATE_ADDR: +- break; +- +- case NWC_CONN_INFO_SERVER_GUID: +- break; +- +- default: +- break; +- } +- +- if (srcData && dataLen) +- { +- cpylen = copy_to_user(connInfo->pConnInfo, srcData, connInfo->uInfoLength); +- } +- +- return; +-} +- +-/*++======================================================================*/ +-int NwGetDaemonVersion(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +- +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCGetRequesterVersion pDVersion; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- datalen = sizeof(*pDVersion); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_GET_REQUESTER_VERSION; +- cmdlen = sizeof(*cmd); +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- pDVersion = (PNwdCGetRequesterVersion)reply->data; +- cpylen = copy_to_user(pDVersion, pdata->reqData, sizeof(*pDVersion)); +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +- +-/*++======================================================================*/ +-int NwcGetPreferredDSTree(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +- +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCGetPreferredDsTree pDGetTree; +-NwcGetPreferredDsTree xplatCall, *p; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +-u_char *dPtr; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcGetPreferredDsTree)); +- datalen = sizeof(*pDGetTree) + xplatCall.uTreeLength; +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_GET_PREFERRED_DS_TREE; +- cmdlen = sizeof(*cmd); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- if (!retCode) +- { +- pDGetTree = (PNwdCGetPreferredDsTree)reply->data; +- dPtr = reply->data + pDGetTree->DsTreeNameOffset; +- p = (NwcGetPreferredDsTree *)pdata->reqData; +- +- DbgPrint("NwcGetPreferredDSTree: Reply recieved\n"); +- DbgPrint(" TreeLen = %x\n", pDGetTree->uTreeLength); +- DbgPrint(" TreeName = %s\n", dPtr); +- +- cpylen = copy_to_user(p, &pDGetTree->uTreeLength, 4); +- cpylen = copy_to_user(xplatCall.pDsTreeName, dPtr, pDGetTree->uTreeLength); +- } +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwcSetPreferredDSTree(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +- +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-PNwdCSetPreferredDsTree pDSetTree; +-NwcSetPreferredDsTree xplatCall; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +-u_char *dPtr; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetPreferredDsTree)); +- datalen = sizeof(*pDSetTree) + xplatCall.uTreeLength; +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SET_PREFERRED_DS_TREE; +- +- pDSetTree = (PNwdCSetPreferredDsTree)cmd->data; +- pDSetTree->DsTreeNameOffset = sizeof(*pDSetTree); +- pDSetTree->uTreeLength = xplatCall.uTreeLength; +- +- dPtr = cmd->data + sizeof(*pDSetTree); +- cpylen = copy_from_user(dPtr, xplatCall.pDsTreeName, xplatCall.uTreeLength); +- +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +- +-/*++======================================================================*/ +-int NwcSetDefaultNameCtx(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +- +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcSetDefaultNameContext xplatCall; +-PNwdCSetDefaultNameContext pDSet; +-u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; +-u_char *dPtr; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetDefaultNameContext)); +- datalen = sizeof(*pDSet) + xplatCall.uTreeLength + xplatCall.uNameLength; +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SET_DEFAULT_NAME_CONTEXT; +- cmd->dataLen = sizeof(NwdCSetDefaultNameContext) + xplatCall.uTreeLength + xplatCall.uNameLength; +- +- pDSet = (PNwdCSetDefaultNameContext)cmd->data; +- dPtr = cmd->data; +- +- pDSet->TreeOffset = sizeof(NwdCSetDefaultNameContext); +- pDSet->uTreeLength = xplatCall.uTreeLength; +- pDSet->NameContextOffset = pDSet->TreeOffset+xplatCall.uTreeLength; +- pDSet->uNameLength = xplatCall.uNameLength; +- +- cpylen = copy_from_user(dPtr+pDSet->TreeOffset, xplatCall.pTreeName, xplatCall.uTreeLength); +- cpylen = copy_from_user(dPtr+pDSet->NameContextOffset, xplatCall.pNameContext, xplatCall.uNameLength); +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwcGetDefaultNameCtx(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +- +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcGetDefaultNameContext xplatCall; +-PNwdCGetDefaultNameContext pGet; +-char *dPtr; +-int retCode = -ENOMEM; +-u_long cmdlen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcGetDefaultNameContext)); +- cmdlen = sizeof(*cmd) + sizeof(NwdCGetDefaultNameContext) + xplatCall.uTreeLength; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_GET_DEFAULT_NAME_CONTEXT; +- cmd->dataLen = sizeof(NwdCGetDefaultNameContext)+xplatCall.uTreeLength; +- +- pGet = (PNwdCGetDefaultNameContext)cmd->data; +- dPtr = cmd->data; +- +- pGet->TreeOffset = sizeof(NwdCGetDefaultNameContext); +- pGet->uTreeLength = xplatCall.uTreeLength; +- +- cpylen = copy_from_user( dPtr + pGet->TreeOffset, xplatCall.pTreeName, xplatCall.uTreeLength); +- dPtr[pGet->TreeOffset+pGet->uTreeLength] = 0; +- +- retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- retCode = reply->Reply.ErrorCode; +- if (!retCode) +- { +- pGet = (PNwdCGetDefaultNameContext)reply->data; +- +- DbgPrint("NwcGetDefaultNameCtx: retCode=0x%x uNameLength1=%d uNameLength2=%d\n", retCode, pGet->uNameLength, xplatCall.uNameLength); +- if (xplatCall.uNameLength < pGet->uNameLength) +- { +- pGet->uNameLength = xplatCall.uNameLength; +- retCode = NWE_BUFFER_OVERFLOW; +- } +- dPtr = (char *)pGet + pGet->NameContextOffset; +- cpylen = copy_to_user(xplatCall.pNameContext, dPtr, pGet->uNameLength); +- } +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(retCode); +- +-} +- +-/*++======================================================================*/ +-int NwQueryFeature(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- NwcQueryFeature xpCall; +- int status = SUCCESS; +- u_long cpylen; +- +- cpylen = copy_from_user(&xpCall, pdata->reqData, sizeof(NwcQueryFeature)); +- switch (xpCall.Feature) +- { +- case NWC_FEAT_NDS: +- case NWC_FEAT_NDS_MTREE: +- case NWC_FEAT_PRN_CAPTURE: +- case NWC_FEAT_NDS_RESOLVE: +- +- status = NWE_REQUESTER_FAILURE; +- +- } +- return( status ); +-} +- +-/*++======================================================================*/ +-int NwcGetTreeMonitoredConn(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcGetTreeMonitoredConnRef xplatCall, *p; +-PNwdCGetTreeMonitoredConnRef pDConnRef; +-char *dPtr; +-u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcGetTreeMonitoredConnRef)); +- datalen = sizeof(*pDConnRef) + xplatCall.pTreeName->DataLen; +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_GET_TREE_MONITORED_CONN_REF; +- +- pDConnRef = (PNwdCGetTreeMonitoredConnRef)cmd->data; +- pDConnRef->TreeName.boffset = sizeof(*pDConnRef); +- pDConnRef->TreeName.len = xplatCall.pTreeName->DataLen; +- pDConnRef->TreeName.type = xplatCall.pTreeName->DataType; +- +- dPtr = cmd->data + sizeof(*pDConnRef); +- cpylen = copy_from_user(dPtr, xplatCall.pTreeName->pBuffer, pDConnRef->TreeName.len); +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- pDConnRef = (PNwdCGetTreeMonitoredConnRef)reply->data; +- dPtr = reply->data + pDConnRef->TreeName.boffset; +- p = (NwcGetTreeMonitoredConnRef *)pdata->reqData; +- cpylen = copy_to_user(&p->uConnReference, &pDConnRef->uConnReference, 4); +- +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- +- } +- +- return(status); +-} +- +-/*++======================================================================*/ +-int NwcEnumIdentities(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcEnumerateIdentities xplatCall, *eId; +-PNwdCEnumerateIdentities pEnum; +-NwcString xferStr; +-char *str; +-u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcEnumerateIdentities)); +- datalen = sizeof(*pEnum); +- cmdlen = datalen + sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_ENUMERATE_IDENTITIES; +- +- DbgPrint("NwcEnumIdentities: Send Request\n"); +- DbgPrint(" iterator = %x\n", xplatCall.Iterator); +- DbgPrint(" cmdlen = %d\n", cmdlen); +- +- pEnum = (PNwdCEnumerateIdentities)cmd->data; +- pEnum->Iterator = xplatCall.Iterator; +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- +- eId = pdata->repData; +- pEnum = (PNwdCEnumerateIdentities)reply->data; +- cpylen = copy_to_user(&eId->Iterator, &pEnum->Iterator, sizeof(pEnum->Iterator)); +- DbgPrint("[XPLAT NWCAPI] Found AuthId 0x%X\n", pEnum->AuthenticationId); +- cpylen = copy_to_user(&eId->AuthenticationId, &pEnum->AuthenticationId, sizeof(pEnum->AuthenticationId)); +- cpylen = copy_to_user(&eId->AuthType, &pEnum->AuthType, sizeof(pEnum->AuthType)); +- cpylen = copy_to_user(&eId->IdentityFlags, &pEnum->IdentityFlags, sizeof(pEnum->IdentityFlags)); +- cpylen = copy_to_user(&eId->NameType, &pEnum->NameType, sizeof(pEnum->NameType)); +- cpylen = copy_to_user(&eId->ObjectType, &pEnum->ObjectType, sizeof(pEnum->ObjectType)); +- +- if (!status) +- { +- cpylen = copy_from_user(&xferStr, eId->pDomainName, sizeof(NwcString)); +- str = (char *)((char *)reply->data + pEnum->domainNameOffset); +- DbgPrint("[XPLAT NWCAPI] Found Domain %s\n", str); +- cpylen = copy_to_user(xferStr.pBuffer, str, pEnum->domainNameLen); +- xferStr.DataType = NWC_STRING_TYPE_ASCII; +- xferStr.DataLen = pEnum->domainNameLen - 1; +- cpylen = copy_to_user(eId->pDomainName, &xferStr, sizeof(NwcString)); +- +- +- cpylen = copy_from_user(&xferStr, eId->pObjectName, sizeof(NwcString)); +- str = (char *)((char *)reply->data + pEnum->objectNameOffset); +- DbgPrint("[XPLAT NWCAPI] Found User %s\n", str); +- cpylen = copy_to_user(xferStr.pBuffer, str, pEnum->objectNameLen); +- xferStr.DataType = NWC_STRING_TYPE_ASCII; +- xferStr.DataLen = pEnum->objectNameLen - 1; +- cpylen = copy_to_user(eId->pObjectName, &xferStr, sizeof(NwcString)); +- } +- +- Novfs_Free(reply); +- +- } +- Novfs_Free(cmd); +- +- } +- return(status); +-} +- +-/*++======================================================================*/ +-int NwcChangeAuthKey(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Change the password on the server +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcChangeKey xplatCall; +-PNwdCChangeKey pNewKey; +-NwcString xferStr; +-char *str; +-u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcChangeKey)); +- +- datalen = sizeof(NwdCChangeKey) + xplatCall.pDomainName->DataLen + xplatCall.pObjectName->DataLen +- + xplatCall.pNewPassword->DataLen + xplatCall.pVerifyPassword->DataLen; +- +- cmdlen = sizeof(*cmd) + datalen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- pNewKey = (PNwdCChangeKey)cmd->data; +- cmd->dataLen = datalen; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_CHANGE_KEY; +- +- pNewKey->NameType = xplatCall.NameType; +- pNewKey->ObjectType = xplatCall.ObjectType; +- pNewKey->AuthType = xplatCall.AuthType; +- str = (char *)pNewKey; +- +- /* +- * Get the tree name +- */ +- str += sizeof(*pNewKey); +- cpylen = copy_from_user(&xferStr, xplatCall.pDomainName, sizeof(NwcString)); +- pNewKey->domainNameOffset = sizeof(*pNewKey); +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->domainNameLen = xferStr.DataLen; +- +- /* +- * Get the User Name +- */ +- str += pNewKey->domainNameLen; +- cpylen = copy_from_user(&xferStr, xplatCall.pObjectName, sizeof(NwcString)); +- pNewKey->objectNameOffset = pNewKey->domainNameOffset + pNewKey->domainNameLen; +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->objectNameLen = xferStr.DataLen; +- +- /* +- * Get the New Password +- */ +- str += pNewKey->objectNameLen; +- cpylen = copy_from_user(&xferStr, xplatCall.pNewPassword, sizeof(NwcString)); +- pNewKey->newPasswordOffset = pNewKey->objectNameOffset + pNewKey->objectNameLen; +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->newPasswordLen = xferStr.DataLen; +- +- /* +- * Get the Verify Password +- */ +- str += pNewKey->newPasswordLen; +- cpylen = copy_from_user(&xferStr, xplatCall.pVerifyPassword, sizeof(NwcString)); +- pNewKey->verifyPasswordOffset = pNewKey->newPasswordOffset + pNewKey->newPasswordLen; +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->verifyPasswordLen = xferStr.DataLen; +- +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- memset(cmd, 0, cmdlen); +- +- Novfs_Free(cmd); +- } +- +- return(status); +-} +- +-/*++======================================================================*/ +-int NwcSetPrimaryConn(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Set the primary connection Id +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcSetPrimaryConnection xplatCall; +-PNwdCSetPrimaryConnection pConn; +-u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetPrimaryConnection)); +- +- datalen = sizeof(NwdCSetPrimaryConnection); +- cmdlen = sizeof(*cmd) + datalen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- pConn = (PNwdCSetPrimaryConnection)cmd->data; +- cmd->dataLen = datalen; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SET_PRIMARY_CONN; +- pConn->ConnHandle = xplatCall.ConnHandle; +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- +- Novfs_Free(cmd); +- } +- +- return(status); +-} +- +-/*++======================================================================*/ +-int NwcGetPrimaryConn(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Get the Primary connection +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-XPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long status = -ENOMEM, cmdlen, replylen, cpylen; +- +- +- cmdlen = (u_long)(&((PXPLAT_CALL_REQUEST)0)->data); +- +- cmd.dataLen = 0; +- cmd.Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd.Command.SequenceNumber = 0; +- cmd.Command.SessionId = Session; +- cmd.NwcCommand = NWC_GET_PRIMARY_CONN; +- +- status = Queue_Daemon_Command((void *)&cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- if (!status) +- { +- cpylen = copy_to_user(pdata->repData, reply->data, sizeof(u_long)); +- } +- +- Novfs_Free(reply); +- } +- +- return(status); +-} +- +- +-/*++======================================================================*/ +-int NwcSetMapDrive(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Get the Primary connection +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long status = 0, datalen, cmdlen, replylen, cpylen; +-NwcMapDriveEx symInfo; +- +- DbgPrint("Call to NwcSetMapDrive\n"); +- cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); +- cmdlen = sizeof(*cmd); +- datalen = sizeof(symInfo) + symInfo.dirPathOffsetLength + symInfo.linkOffsetLength; +- +- DbgPrint(" cmdlen = %d\n", cmdlen); +- DbgPrint(" dataLen = %d\n", datalen); +- DbgPrint(" symInfo.dirPathOffsetLength = %d\n", symInfo.dirPathOffsetLength); +- DbgPrint(" symInfo.linkOffsetLength = %d\n", symInfo.linkOffsetLength); +- DbgPrint(" pdata->datalen = %d\n", pdata->reqLen); +- +- mydump(sizeof(symInfo), &symInfo); +- +- cmdlen += datalen; +- +- +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->dataLen = datalen; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_MAP_DRIVE; +- +- cpylen = copy_from_user(cmd->data, pdata->reqData, datalen); +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(status); +- +-} +- +-/*++======================================================================*/ +-int NwcUnMapDrive(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Get the Primary connection +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long status = 0, datalen, cmdlen, replylen, cpylen; +-NwcUnmapDriveEx symInfo; +- +- DbgPrint("Call to NwcUnMapDrive\n"); +- +- cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); +- cmdlen = sizeof(*cmd); +- datalen = sizeof(symInfo) + symInfo.linkLen; +- +- cmdlen += datalen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->dataLen = datalen; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_UNMAP_DRIVE; +- +- cpylen = copy_from_user(cmd->data, pdata->reqData, datalen); +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- +- return(status); +-} +- +- +-/*++======================================================================*/ +-int NwcEnumerateDrives(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Get the Primary connection +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long status = 0, cmdlen, replylen, cpylen; +-u_long offset; +-char *cp; +- +- DbgPrint("Call to NwcEnumerateDrives\n"); +- +- cmdlen = sizeof(*cmd); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- cmd->dataLen = 0; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_ENUMERATE_DRIVES; +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- DbgPrint("Status Code = 0x%X\n", status); +- if (!status) +- { +- offset = sizeof(u_long); +- cp = reply->data; +- replylen = ((PNwcGetMappedDrives)pdata->repData)->MapBuffLen; +- cpylen = copy_to_user(pdata->repData, cp, offset); +- cp += offset; +- cpylen = copy_to_user(((PNwcGetMappedDrives)pdata->repData)->MapBuffer, cp, min(replylen - offset, reply->dataLen - offset)); +- } +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- +- return(status); +-} +- +- +-/*++======================================================================*/ +-int NwcGetBroadcastMessage(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Get the Primary connection +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-u_long status = 0x8866, cmdlen, replylen, cpylen; +-NwcGetBroadcastNotification msg; +-PNwdCGetBroadcastNotification dmsg; +- +- cmdlen = sizeof(*cmd) + sizeof(*dmsg); +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- if (cmd) +- { +- +- cpylen = copy_from_user(&msg, pdata->reqData, sizeof(msg)); +- cmd->dataLen = sizeof(*dmsg); +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- +- cmd->NwcCommand = NWC_GET_BROADCAST_MESSAGE; +- dmsg = (PNwdCGetBroadcastNotification)cmd->data; +- dmsg->uConnReference = msg.uConnReference; +- +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- DbgPrint("Status Code = 0x%X\n", status); +- if (!status) +- { +- /* we have a message so copy it to the user buffer */ +- cpylen = copy_to_user(pdata->repData, reply->data, min(pdata->repLen, reply->dataLen)); +- } +- else +- { +- msg.messageLen = 0; +- msg.message[0] = 0; +- cpylen = copy_to_user(pdata->repData, &msg, sizeof(msg)); +- } +- +- Novfs_Free(reply); +- } +- Novfs_Free(cmd); +- } +- return(status); +- +-} +- +- +-int NwdSetKeyValue(PXPLAT pdata, session_t Session) +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcSetKey xplatCall; +-PNwdCSetKey pNewKey; +-NwcString cstrObjectName, cstrPassword; +-char *str; +-u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetKey)); +- cpylen = copy_from_user(&cstrObjectName, xplatCall.pObjectName, sizeof(NwcString)); +- cpylen = copy_from_user(&cstrPassword, xplatCall.pNewPassword, sizeof(NwcString)); +- +- datalen = sizeof(NwdCSetKey) + cstrObjectName.DataLen + cstrPassword.DataLen; +- +- cmdlen = sizeof(*cmd) + datalen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- pNewKey = (PNwdCSetKey)cmd->data; +- cmd->dataLen = datalen; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_SET_KEY; +- +- pNewKey->ObjectType = xplatCall.ObjectType; +- pNewKey->AuthenticationId = xplatCall.AuthenticationId; +- pNewKey->ConnHandle = xplatCall.ConnHandle; +- str = (char *)pNewKey; +- +- /* +- * Get the User Name +- */ +- str += sizeof(NwdCSetKey); +- cpylen = copy_from_user(str, cstrObjectName.pBuffer, cstrObjectName.DataLen); +- +- str += +- pNewKey->objectNameLen = cstrObjectName.DataLen; +- pNewKey->objectNameOffset = sizeof(NwdCSetKey); +- +- /* +- * Get the Verify Password +- */ +- cpylen = copy_from_user(str, cstrPassword.pBuffer, cstrPassword.DataLen); +- +- pNewKey->newPasswordLen = cstrPassword.DataLen; +- pNewKey->newPasswordOffset = pNewKey->objectNameOffset+pNewKey->objectNameLen; +- +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- memset(cmd, 0, cmdlen); +- Novfs_Free(cmd); +- } +- +- return(status); +-} +- +-/*++======================================================================*/ +-int NwdVerifyKeyValue(PXPLAT pdata, session_t Session) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: Change the password on the server +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +-PXPLAT_CALL_REQUEST cmd; +-PXPLAT_CALL_REPLY reply; +-NwcVerifyKey xplatCall; +-PNwdCVerifyKey pNewKey; +-NwcString xferStr; +-char *str; +-u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; +- +- cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcVerifyKey)); +- +- datalen = sizeof(NwdCVerifyKey) + xplatCall.pDomainName->DataLen + xplatCall.pObjectName->DataLen +- + xplatCall.pVerifyPassword->DataLen; +- +- cmdlen = sizeof(*cmd) + datalen; +- cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); +- +- if (cmd) +- { +- pNewKey = (PNwdCVerifyKey)cmd->data; +- cmd->dataLen = datalen; +- cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; +- cmd->Command.SequenceNumber = 0; +- cmd->Command.SessionId = Session; +- cmd->NwcCommand = NWC_VERIFY_KEY; +- +- pNewKey->NameType = xplatCall.NameType; +- pNewKey->ObjectType = xplatCall.ObjectType; +- pNewKey->AuthType = xplatCall.AuthType; +- str = (char *)pNewKey; +- +- /* +- * Get the tree name +- */ +- str += sizeof(*pNewKey); +- cpylen = copy_from_user(&xferStr, xplatCall.pDomainName, sizeof(NwcString)); +- pNewKey->domainNameOffset = sizeof(*pNewKey); +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->domainNameLen = xferStr.DataLen; +- +- /* +- * Get the User Name +- */ +- str += pNewKey->domainNameLen; +- cpylen = copy_from_user(&xferStr, xplatCall.pObjectName, sizeof(NwcString)); +- pNewKey->objectNameOffset = pNewKey->domainNameOffset + pNewKey->domainNameLen; +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->objectNameLen = xferStr.DataLen; +- +- /* +- * Get the Verify Password +- */ +- str += pNewKey->objectNameLen; +- cpylen = copy_from_user(&xferStr, xplatCall.pVerifyPassword, sizeof(NwcString)); +- pNewKey->verifyPasswordOffset = pNewKey->objectNameOffset + pNewKey->objectNameLen; +- cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); +- pNewKey->verifyPasswordLen = xferStr.DataLen; +- +- status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); +- if (reply) +- { +- status = reply->Reply.ErrorCode; +- Novfs_Free(reply); +- } +- memset(cmd, 0, cmdlen); +- Novfs_Free(cmd); +- } +- +- return(status); +-} +diff -uNr src.old/novfs/proc.c src/novfs/proc.c +--- src.old/novfs/proc.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/proc.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,339 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: proc.c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module contains functions that create the +- * interface to the proc filesystem. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +-#include +-#include +-#include +-#include +- +-/*===[ Include files specific to this module ]============================*/ +-#include "vfs.h" +- +-/*===[ External data ]====================================================*/ +-extern char *Novfs_CurrentMount; +- +-/*===[ External prototypes ]==============================================*/ +-extern int DbgPrint( char *Fmt, ... ); +- +-extern ssize_t +-Daemon_Receive_Reply(struct file *file, const char *buf, size_t nbytes, loff_t *ppos); +- +-extern ssize_t +-Daemon_Send_Command(struct file *file, char *buf, size_t len, loff_t *off); +- +-extern int Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +- +-extern int Daemon_Library_close(struct inode *inode, struct file *file); +-extern int Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +-extern int Daemon_Library_open(struct inode *inode, struct file *file); +-extern ssize_t Daemon_Library_read(struct file *file, char *buf, size_t len, loff_t *off); +-extern ssize_t Daemon_Library_write(struct file *file, const char *buf, size_t len, loff_t *off); +-extern loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin); +- +-extern int Daemon_Open_Control(struct inode *Inode, struct file *File); +-extern int Daemon_Close_Control(struct inode *Inode, struct file *File); +- +-extern int Daemon_getversion( char *Buf, int Length ); +- +-/*===[ Manifest constants ]===============================================*/ +- +-/*===[ Type definitions ]=================================================*/ +- +-/*===[ Function prototypes ]==============================================*/ +-ssize_t +-Novfs_User_proc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos); +- +-ssize_t +-Novfs_User_proc_write(struct file * file, char * buf, size_t nbytes, loff_t *ppos); +- +-int Novfs_User_proc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +- +-int Init_Procfs_Interface( void ); +-void Uninit_Procfs_Interface( void ); +- +-/*===[ Global variables ]=================================================*/ +-struct proc_dir_entry *Novfs_Procfs_dir, *Novfs_Control, *Novfs_Library, *Novfs_Version; +-static struct file_operations Daemon_proc_fops; +-static struct file_operations Library_proc_fops; +- +-/*===[ Code ]=============================================================*/ +- +-/*++======================================================================*/ +-int Novfs_Get_Version(char *page, char **start, off_t off, int count, int *eof, void *data) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *buf, tbuf[48]; +- int len=0, i; +- +- if ( !off ) +- { +- buf = page+off; +- *start = buf; +- len = sprintf(buf, "Novfs Version=%s\n", NOVFS_VERSION_STRING); +- i = Daemon_getversion(tbuf, sizeof(tbuf)); +- if ((i > 0) && i < (count-len)) +- { +- len += sprintf(buf+len, "Novfsd Version=%s\n", tbuf); +- } +- +- if (Novfs_CurrentMount) +- { +- i = strlen(Novfs_CurrentMount); +- if ((i > 0) && i < (count-len)) +- { +- len += sprintf(buf+len, "Novfs mount=%s\n", Novfs_CurrentMount); +- } +- } +- DbgPrint("Novfs_Get_Version:\n%s\n", buf); +- } +- *eof = 1; +- return(len); +-} +- +-/*++======================================================================*/ +-ssize_t +-Novfs_User_proc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- ssize_t retval=0; +- +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(buf); +- UNUSED_VARIABLE(nbytes); +- UNUSED_VARIABLE(ppos); +- +- DbgPrint( "Novfs_User_proc_read: kernel_locked 0x%x\n", kernel_locked()); +- +- return retval; +-} +-/*++======================================================================*/ +-ssize_t +-Novfs_User_proc_write(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- ssize_t retval=0; +- +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(ppos); +- +- DbgPrint( "Novfs_User_proc_write: kernel_locked 0x%x\n", kernel_locked()); +- if (buf && nbytes) +- { +- } +- +- return(retval); +-} +- +-/*++======================================================================*/ +-int Novfs_User_proc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retval=-ENOSYS; +- +- UNUSED_VARIABLE(inode); +- UNUSED_VARIABLE(file); +- UNUSED_VARIABLE(cmd); +- UNUSED_VARIABLE(arg); +- +- DbgPrint( "Novfs_User_proc_ioctl: kernel_locked 0x%x\n", kernel_locked()); +- +- return(retval); +-} +- +-/*++======================================================================*/ +-int Init_Procfs_Interface( void ) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- int retCode=0; +- +- Novfs_Procfs_dir = proc_mkdir(MODULE_NAME, NULL); +- if ( Novfs_Procfs_dir ) +- { +- Novfs_Procfs_dir->owner = THIS_MODULE; +- +- Novfs_Control = create_proc_entry("Control", 0600, Novfs_Procfs_dir); +- +- if ( Novfs_Control ) +- { +- Novfs_Control->owner = THIS_MODULE; +- Novfs_Control->size = 0; +- memcpy(&Daemon_proc_fops, Novfs_Control->proc_fops, sizeof(struct file_operations)); +- +- /* +- * Setup our functions +- */ +- Daemon_proc_fops.owner = THIS_MODULE; +- Daemon_proc_fops.open = Daemon_Open_Control; +- Daemon_proc_fops.release = Daemon_Close_Control; +- Daemon_proc_fops.read = Daemon_Send_Command; +- Daemon_proc_fops.write = Daemon_Receive_Reply; +- Daemon_proc_fops.ioctl = Daemon_ioctl; +- +- Novfs_Control->proc_fops = &Daemon_proc_fops; +- } +- else +- { +- remove_proc_entry(MODULE_NAME, NULL); +- return(-ENOENT); +- } +- +- Novfs_Library = create_proc_entry("Library", 0666, Novfs_Procfs_dir); +- if ( Novfs_Library ) +- { +- Novfs_Library->owner = THIS_MODULE; +- Novfs_Library->size = 0; +- +- /* +- * Setup our file functions +- */ +- memcpy(&Library_proc_fops, Novfs_Library->proc_fops, sizeof(struct file_operations)); +- Library_proc_fops.owner = THIS_MODULE; +- Library_proc_fops.open = Daemon_Library_open; +- Library_proc_fops.release = Daemon_Library_close; +- Library_proc_fops.read = Daemon_Library_read; +- Library_proc_fops.write = Daemon_Library_write; +- Library_proc_fops.llseek = Daemon_Library_llseek; +- Library_proc_fops.ioctl = Daemon_Library_ioctl; +- Novfs_Library->proc_fops = &Library_proc_fops; +- } +- else +- { +- remove_proc_entry("Control", Novfs_Procfs_dir); +- remove_proc_entry(MODULE_NAME, NULL); +- return(-ENOENT); +- } +- +- Novfs_Version = create_proc_read_entry("Version", 0444, Novfs_Procfs_dir, Novfs_Get_Version, NULL); +- if ( Novfs_Version ) +- { +- Novfs_Version->owner = THIS_MODULE; +- Novfs_Version->size = 0; +- } +- else +- { +- remove_proc_entry("Library", Novfs_Procfs_dir); +- remove_proc_entry("Control", Novfs_Procfs_dir); +- remove_proc_entry(MODULE_NAME, NULL); +- retCode = -ENOENT; +- } +- } +- else +- { +- retCode = -ENOENT; +- } +- return(retCode); +-} +- +-/*++======================================================================*/ +-void Uninit_Procfs_Interface( void ) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- +- DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Version, NULL)\n"); +- remove_proc_entry("Version", Novfs_Procfs_dir); +- +- DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Control, NULL)\n"); +- remove_proc_entry("Control", Novfs_Procfs_dir); +- +- DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Library, NULL)\n"); +- remove_proc_entry("Library", Novfs_Procfs_dir); +- +- DbgPrint("Uninit_Procfs_Interface remove_proc_entry(%s, NULL)\n", MODULE_NAME); +- remove_proc_entry(MODULE_NAME, NULL); +- +- DbgPrint("Uninit_Procfs_Interface done\n"); +-} +diff -uNr src.old/novfs/profile.c src/novfs/profile.c +--- src.old/novfs/profile.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/profile.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,1201 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: profile.c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module contains a debugging code for +- * the novfs VFS. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-/*===[ Include files specific to this module ]============================*/ +-#include "vfs.h" +- +-/*===[ External data ]====================================================*/ +-extern struct dentry *Novfs_root; +-extern struct proc_dir_entry *Novfs_Procfs_dir; +-extern unsigned long File_update_timeout; +- +-/*===[ External prototypes ]==============================================*/ +-extern void Scope_Dump_Tasklist( void ); +-extern void Scope_Dump_Scopetable( void ); +-extern void Daemon_Dumpque( void ); +-extern char *Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags); +-extern int Novfs_dump_inode_cache(int argc, const char **argv, const char **envp, struct pt_regs *regs); +-extern void Novfs_dump_inode( void *pf ); +-extern int Daemon_SendDebugCmd ( char *Command ); +- +- +-/*===[ Manifest constants ]===============================================*/ +-#define DBGBUFFERSIZE (1024*1024*32) +- +-/*===[ Type definitions ]=================================================*/ +-typedef void daemon_command_t; +- +-typedef struct _SYMBOL_TABLE { +- void *address; +- char *name; +-} SYMBOL_TABLE, *PSYMBOL_TABLE; +- +-struct local_rtc_time { +- int tm_sec; +- int tm_min; +- int tm_hour; +- int tm_mday; +- int tm_mon; +- int tm_year; +- int tm_wday; +- int tm_yday; +- int tm_isdst; +-}; +- +-/*===[ Function prototypes ]==============================================*/ +-int profile_task_exit_callback(struct notifier_block *self, unsigned long val, void *data) __attribute__((__no_instrument_function__)); +-int init_profile( void ); +- +-char *ctime_r(time_t *clock, char *buf); +-int LocalPrint( char *Fmt, ... ) __attribute__((__no_instrument_function__)); +-int DbgPrint( char *Fmt, ... ) __attribute__((__no_instrument_function__)); +- +-void __cyg_profile_func_enter (void *this_fn, void *call_site) __attribute__((__no_instrument_function__)) ; +-void __cyg_profile_func_exit (void *this_fn, void *call_site) __attribute__((__no_instrument_function__)); +-void doline(unsigned char *b, unsigned char *p, unsigned char *l) __attribute__((__no_instrument_function__)); +-void mydump(int size, void *dumpptr) __attribute__((__no_instrument_function__)); +-void GregorianDay(struct local_rtc_time * tm) __attribute__((__no_instrument_function__)); +-void to_tm(int tim, struct local_rtc_time * tm) __attribute__((__no_instrument_function__)); +-char *ctime_r(time_t *clock, char *buf) __attribute__((__no_instrument_function__)); +-int profile_dump_tasklist(int argc, const char **argv, const char **envp, struct pt_regs *regs); +-int profile_dump_scopetable(int argc, const char **argv, const char **envp, struct pt_regs *regs); +-int profile_dump_daemonque(int argc, const char **argv, const char **envp, struct pt_regs *regs); +-int profile_dump_DbgBuffer(int argc, const char **argv, const char **envp, struct pt_regs *regs); +-int profile_dump_DentryTree(int argc, const char **argv, const char **envp, struct pt_regs *regs); +-int profile_dump_inode(int argc, const char **argv, const char **envp, struct pt_regs *regs); +- +-void *Novfs_Malloc( size_t size, int flags ) __attribute__((__no_instrument_function__)); +-void Novfs_Free( const void *p ) __attribute__((__no_instrument_function__)); +- +-int profile_dump_memorylist_dbg(int argc, const char **argv, const char **envp, struct pt_regs *regs) __attribute__((__no_instrument_function__)); +-void profile_dump_memorylist( void *pf ); +- +-static ssize_t User_proc_write_DbgBuffer(struct file * file, const char __user *buf, size_t nbytes, loff_t *ppos) __attribute__((__no_instrument_function__)); +-static ssize_t User_proc_read_DbgBuffer(struct file * file, char * buf, size_t nbytes, loff_t *ppos) __attribute__((__no_instrument_function__)); +-static int proc_read_DbgBuffer(char *page, char **start, +- off_t off, int count, +- int *eof, void *data) __attribute__((__no_instrument_function__)); +- +-void profile_dump_dt(struct dentry *parent, void *pf ); +-ssize_t profile_inode_read(struct file *file, char *buf, size_t len, loff_t *off); +-ssize_t profile_dentry_read(struct file *file, char *buf, size_t len, loff_t *off); +-ssize_t profile_memory_read(struct file *file, char *buf, size_t len, loff_t *off); +- +-/*===[ Global variables ]=================================================*/ +-char *DbgPrintBuffer=NULL; +-char DbgPrintOn=0; +-char DbgSyslogOn=0; +-char DbgProfileOn=0; +-char DbgDaemonLogOn=0; +-unsigned long DbgPrintBufferOffset=0; +-unsigned long DbgPrintBufferReadOffset=0; +-unsigned long DbgPrintBufferSize = DBGBUFFERSIZE; +- +-int Indent = 0; +-char IndentString[] = " "; +- +-static struct file_operations Dbg_proc_file_operations; +-static struct file_operations dentry_proc_file_ops; +-static struct file_operations inode_proc_file_ops; +-static struct file_operations memory_proc_file_ops; +- +-static struct proc_dir_entry *dbg_dir, *dbg_file; +-static struct proc_dir_entry *dentry_file; +-static struct proc_dir_entry *inode_file; +-static struct proc_dir_entry *memory_file; +- +-static struct notifier_block taskexit_nb; +- +- +-DECLARE_MUTEX(LocalPrint_lock); +-spinlock_t Syslog_lock = SPIN_LOCK_UNLOCKED; +- +-#include "profile_funcs.h" +- +- +-/*===[ Code ]=============================================================*/ +-int +-profile_task_exit_callback(struct notifier_block *self, unsigned long val, void *data) +-{ +- struct task_struct *task = (struct task_struct *)data; +- +- DbgPrint("profile_task_exit_callback: task 0x%p %u exiting %s\n", task, task->pid, task->comm); +- return(0); +-} +- +-int init_profile( void ) +-{ +- int retCode = 0; +- +- if ( DbgPrintBuffer ) +- { +- if (Novfs_Procfs_dir) +- { +- dbg_dir = Novfs_Procfs_dir; +- } +- else +- { +- dbg_dir = proc_mkdir(MODULE_NAME, NULL); +- } +- +- if( dbg_dir ) +- { +- dbg_dir->owner = THIS_MODULE; +- dbg_file = create_proc_read_entry("Debug", +- 0600, +- dbg_dir, +- proc_read_DbgBuffer, +- NULL); +- if ( dbg_file ) +- { +- dbg_file->owner = THIS_MODULE; +- dbg_file->size = DBGBUFFERSIZE; +- memcpy(&Dbg_proc_file_operations, dbg_file->proc_fops, sizeof(struct file_operations)); +- Dbg_proc_file_operations.read = User_proc_read_DbgBuffer; +- Dbg_proc_file_operations.write = User_proc_write_DbgBuffer; +- dbg_file->proc_fops = &Dbg_proc_file_operations; +- } +- else +- { +- remove_proc_entry(MODULE_NAME, NULL); +- vfree( DbgPrintBuffer ); +- DbgPrintBuffer = NULL; +- } +- +- inode_file = create_proc_entry("inode", +- 0600, +- dbg_dir); +- if ( inode_file ) +- { +- inode_file->owner = THIS_MODULE; +- inode_file->size = 0; +- memcpy(&inode_proc_file_ops, inode_file->proc_fops, sizeof(struct file_operations)); +- inode_proc_file_ops.owner = THIS_MODULE; +- inode_proc_file_ops.read = profile_inode_read; +- inode_file->proc_fops = &inode_proc_file_ops; +- } +- +- dentry_file = create_proc_entry("dentry", +- 0600, +- dbg_dir); +- if ( dentry_file ) +- { +- dentry_file->owner = THIS_MODULE; +- dentry_file->size = 0; +- memcpy(&dentry_proc_file_ops, dentry_file->proc_fops, sizeof(struct file_operations)); +- dentry_proc_file_ops.owner = THIS_MODULE; +- dentry_proc_file_ops.read = profile_dentry_read; +- dentry_file->proc_fops = &dentry_proc_file_ops; +- } +- +- memory_file = create_proc_entry("memory", +- 0600, +- dbg_dir); +- if ( memory_file ) +- { +- memory_file->owner = THIS_MODULE; +- memory_file->size = 0; +- memcpy(&memory_proc_file_ops, memory_file->proc_fops, sizeof(struct file_operations)); +- memory_proc_file_ops.owner = THIS_MODULE; +- memory_proc_file_ops.read = profile_memory_read; +- memory_file->proc_fops = &memory_proc_file_ops; +- } +- +- } +- else +- { +- vfree( DbgPrintBuffer ); +- DbgPrintBuffer = NULL; +- } +- } +- return( retCode ); +-} +- +-/* +-void uninit_profile() +-{ +- if (dbg_file) DbgPrint("Calling remove_proc_entry(Debug, NULL)\n"), remove_proc_entry( "Debug", dbg_dir ); +- if (inode_file) DbgPrint("Calling remove_proc_entry(inode, NULL)\n"), remove_proc_entry( "inode", dbg_dir ); +- if (dentry_file) DbgPrint("Calling remove_proc_entry(dentry, NULL)\n"), remove_proc_entry( "dentry", dbg_dir ); +- if (memory_file) DbgPrint("Calling remove_proc_entry(memory, NULL)\n"), remove_proc_entry( "memory", dbg_dir ); +- +- if (dbg_dir && (dbg_dir != Novfs_Procfs_dir)) +- { +- DbgPrint("Calling remove_proc_entry(%s, NULL)\n", MODULE_NAME); +- remove_proc_entry( MODULE_NAME, NULL ); +- } +-} +-*/ +- +-static +-ssize_t +-User_proc_write_DbgBuffer(struct file * file, const char __user *buf, size_t nbytes, loff_t *ppos) +-{ +- ssize_t retval=nbytes; +- u_char *lbuf, *p; +- int i; +- u_long cpylen; +- +- +- UNUSED_VARIABLE( *ppos ); +- +- lbuf = Novfs_Malloc(nbytes+1, GFP_KERNEL); +- if (lbuf) +- { +- cpylen = copy_from_user(lbuf, buf, nbytes); +- +- lbuf[nbytes] = 0; +- DbgPrint("User_proc_write_DbgBuffer: %s\n", lbuf); +- +- for (i=0; lbuf[i] && lbuf[i] != '\n'; i++) ; +- +- if ( '\n' == lbuf[i] ) +- { +- lbuf[i] = '\0'; +- } +- +- if ( !strcmp("on", lbuf)) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- DbgPrintOn = 1; +- } +- else if ( !strcmp("off", lbuf)) +- { +- DbgPrintOn = 0; +- } +- else if ( !strcmp("reset", lbuf)) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- } +- else if ( NULL != (p = strchr(lbuf, ' '))) +- { +- *p++ = '\0'; +- if ( !strcmp("syslog", lbuf)) +- { +- +- if (!strcmp("on", p)) +- { +- DbgSyslogOn = 1; +- } +- else if (!strcmp("off", p)) +- { +- DbgSyslogOn = 0; +- } +- } +- else if ( !strcmp("profile", lbuf)) +- { +- +- if (!strcmp("on", p)) +- { +- DbgProfileOn = 1; +- } +- else if (!strcmp("off", p)) +- { +- DbgProfileOn = 0; +- } +- } +- else if ( !strcmp("daemonlog", lbuf)) +- { +- +- if (!strcmp("on", p)) +- { +- DbgDaemonLogOn = 1; +- } +- else if (!strcmp("off", p)) +- { +- DbgDaemonLogOn = 0; +- } +- } +- else if ( !strcmp("novfsd", lbuf)) +- { +- Daemon_SendDebugCmd( p ); +- } +- else if ( !strcmp("file_update_timeout", lbuf)) +- { +- File_update_timeout = simple_strtoul(p, NULL, 0); +- } +- } +- Novfs_Free(lbuf); +- } +- +- return (retval); +-} +- +-static +-ssize_t +-User_proc_read_DbgBuffer(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +- +-{ +- ssize_t retval=0; +- size_t count; +- +- UNUSED_VARIABLE( *ppos ); +- +- if (0 != (count = DbgPrintBufferOffset - DbgPrintBufferReadOffset)) +- { +- +- if (count > nbytes) +- { +- count = nbytes; +- } +- +- count -= copy_to_user(buf, &DbgPrintBuffer[DbgPrintBufferReadOffset], count); +- +- if (count == 0) +- { +- if (retval == 0) +- retval = -EFAULT; +- } +- else +- { +- DbgPrintBufferReadOffset += count; +- if (DbgPrintBufferReadOffset >= DbgPrintBufferOffset) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- } +- retval = count; +- } +- } +- +- return retval; +-} +- +-static +-int +-proc_read_DbgBuffer(char *page, char **start, +- off_t off, int count, +- int *eof, void *data) +-{ +- int len; +- static char bufd[512]; +- +- UNUSED_VARIABLE(start); +- UNUSED_VARIABLE(eof); +- UNUSED_VARIABLE(data); +- +- sprintf(bufd, KERN_ALERT "proc_read_DbgBuffer: off=%ld count=%d DbgPrintBufferOffset=%lu DbgPrintBufferReadOffset=%lu\n", +- off, count, DbgPrintBufferOffset, DbgPrintBufferReadOffset); +- printk(bufd); +- +- len = DbgPrintBufferOffset - DbgPrintBufferReadOffset; +- +- if ((int)(DbgPrintBufferOffset-DbgPrintBufferReadOffset) > count) +- { +- len = count; +- } +- +- if (len) +- { +- memcpy(page, &DbgPrintBuffer[DbgPrintBufferReadOffset], len); +- DbgPrintBufferReadOffset += len; +- } +- +- +- if (DbgPrintBufferReadOffset >= DbgPrintBufferOffset) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- } +- +- sprintf(bufd, KERN_ALERT "proc_read_DbgBuffer: return %d\n", len); +- printk(bufd); +- +- return len; +-} +- +-#define DBG_BUFFER_SIZE (2*1024) +- +-int +-LocalPrint( char *Fmt, ... ) +-{ +- int len=0; +- va_list args; +- +- if (DbgPrintBuffer) +- { +- va_start(args, Fmt); +- len += vsnprintf(DbgPrintBuffer+DbgPrintBufferOffset, DbgPrintBufferSize-DbgPrintBufferOffset, Fmt, args); +- DbgPrintBufferOffset += len; +- } +- +- return(len); +-} +- +- +-int +-DbgPrint( char *Fmt, ... ) +-{ +- char *buf; +- int len=0; +- unsigned long offset; +- va_list args; +- +- if ( (DbgPrintBuffer && DbgPrintOn) || DbgSyslogOn ) +- { +- buf = kmalloc( DBG_BUFFER_SIZE, GFP_KERNEL ); +- +- if (buf) +- { +- va_start(args, Fmt); +- len = sprintf(buf, "[%d] ", current->pid); +- +- len += vsnprintf(buf+len, DBG_BUFFER_SIZE-len, Fmt, args); +- if ( -1 == len ) +- { +- len = DBG_BUFFER_SIZE-1; +- buf[len] = '\0'; +- } +- /* +- len = sprintf(&DbgPrintBuffer[offset], "[%llu] ", ts); +- len += vsprintf(&DbgPrintBuffer[offset+len], Fmt, args); +- */ +- +- if (len) +- { +- if (DbgSyslogOn) +- { +- spin_lock( &Syslog_lock ); +- printk("<6>%s", buf); +- spin_unlock( &Syslog_lock ); +- } +- +- if ( DbgPrintBuffer && DbgPrintOn ) +- { +- if ((DbgPrintBufferOffset+len) > DbgPrintBufferSize) +- { +- offset = DbgPrintBufferOffset; +- DbgPrintBufferOffset = 0; +- memset(&DbgPrintBuffer[offset], 0, DbgPrintBufferSize-offset); +- } +- +- mb(); +- +- if ((DbgPrintBufferOffset+len) < DbgPrintBufferSize) +- { +- DbgPrintBufferOffset += len; +- offset = DbgPrintBufferOffset-len; +- memcpy(&DbgPrintBuffer[offset], buf, len+1); +- } +- } +- } +- kfree(buf); +- } +- } +- +- return(len); +-} +- +-void +-__cyg_profile_func_enter (void *this_fn, void *call_site) +-{ +- PSYMBOL_TABLE sym; +- struct timespec ts; +- +- +- if ((void *)init_novfs == this_fn) +- { +- DbgPrintBuffer = vmalloc(DBGBUFFERSIZE); +- taskexit_nb.notifier_call = profile_task_exit_callback; +- +-#ifdef CONFIG_KDB +- kdb_register("novfs_tl", profile_dump_tasklist, "", "Dumps task list", 0); +- kdb_register("novfs_st", profile_dump_scopetable, "", "Dumps the novfs scope table", 0); +- kdb_register("novfs_dque", profile_dump_daemonque, "", "Dumps the novfs daemon que", 0); +- kdb_register("novfs_db", profile_dump_DbgBuffer, "[-r] [-e size] [-i]", "Dumps the novfs DbgBuffer", 0); +- kdb_register("novfs_den", profile_dump_DentryTree, "[dentry]", "Dumps a Dentry tree", 0); +- kdb_register("novfs_ic", Novfs_dump_inode_cache, "[inode]", "Dumps a Inode Cache", 0); +- kdb_register("novfs_inode", profile_dump_inode, "", "Dump allocated Inodes", 0); +- kdb_register("novfs_mem", profile_dump_memorylist_dbg, "", "Dumps allocated memory", 0); +-#endif +- } +- else if (exit_novfs == this_fn) +- { +- if (dbg_file) DbgPrint("Calling remove_proc_entry(Debug, NULL)\n"), remove_proc_entry( "Debug", dbg_dir ); +- if (inode_file) DbgPrint("Calling remove_proc_entry(inode, NULL)\n"), remove_proc_entry( "inode", dbg_dir ); +- if (dentry_file) DbgPrint("Calling remove_proc_entry(dentry, NULL)\n"), remove_proc_entry( "dentry", dbg_dir ); +- if (memory_file) DbgPrint("Calling remove_proc_entry(memory, NULL)\n"), remove_proc_entry( "memory", dbg_dir ); +- +- if (dbg_dir && (dbg_dir != Novfs_Procfs_dir)) +- { +- printk( KERN_INFO "Calling remove_proc_entry(%s, NULL)\n", MODULE_NAME); +- remove_proc_entry( MODULE_NAME, NULL ); +- } +- } +- +- if (DbgProfileOn) +- { +- sym = SymbolTable; +- while (sym->address) +- { +- if (this_fn == sym->address ) +- { +- ts = current_kernel_time(); +- DbgPrint("[%ld:lu]%sS %s (0x%p 0x%p)\n", ts.tv_sec, ts.tv_nsec, &IndentString[sizeof(IndentString)-Indent-1], sym->name, this_fn, call_site); +- +- Indent++; +- if (Indent > (int)(sizeof(IndentString)-1)) +- Indent--; +- +- break; +- } +- sym++; +- } +- } +-} +- +-void +-__cyg_profile_func_exit (void *this_fn, void *call_site) +-{ +- PSYMBOL_TABLE sym; +- struct timespec ts; +- +- if (exit_novfs == this_fn) +- { +- if (DbgPrintBuffer) vfree( DbgPrintBuffer ); +- DbgPrintBuffer = NULL; +- +-#ifdef CONFIG_KDB +- kdb_unregister("novfs_tl"); +- kdb_unregister("novfs_st"); +- kdb_unregister("novfs_dque"); +- kdb_unregister("novfs_db"); +- kdb_unregister("novfs_den"); +- kdb_unregister("novfs_ic"); +- kdb_unregister("novfs_inode"); +- kdb_unregister("novfs_mem"); +-#endif +- return; +- } +- +- if (DbgProfileOn) +- { +- sym = SymbolTable; +- while (sym->address) +- { +- if (this_fn == sym->address ) +- { +- Indent--; +- if (Indent < 0) +- Indent = 0; +- +- ts = current_kernel_time(); +- DbgPrint("[%ld:lu]%sR %s (0x%p)\n", ts.tv_sec, ts.tv_nsec, &IndentString[sizeof(IndentString)-Indent-1], sym->name, call_site); +- break; +- } +- sym++; +- } +- } +-} +- +-void +-doline(unsigned char *b, unsigned char *e, unsigned char *l) +-{ +- *b++ = ' '; +- while (l < e) { +- if ((*l < ' ') || (*l > '~')) +- { +- *b++ = '.'; +- *b = '\0'; +- } +- else +- { +- b += sprintf(b, "%c", *l); +- } +- l++; +- } +-} +- +-void +-mydump(int size, void *dumpptr) +-{ +- unsigned char *ptr = (unsigned char *)dumpptr; +- unsigned char *line=0, buf[80], *bptr=buf; +- int i; +- +- if ( DbgPrintBuffer ) +- { +- if (size) +- { +- for (i=0; i < size; i++) +- { +- if (0 == (i % 16)) +- { +- if (line) +- { +- doline(bptr, ptr, line); +- DbgPrint("%s\n", buf); +- bptr = buf; +- } +- bptr += sprintf(bptr, "0x%p: ", ptr); +- line = ptr; +- } +- bptr += sprintf(bptr, "%02x ", *ptr++); +- } +- doline(bptr, ptr, line); +- DbgPrint("%s\n", buf); +- } +- } +-} +- +-#define FEBRUARY 2 +-#define STARTOFTIME 1970 +-#define SECDAY 86400L +-#define SECYR (SECDAY * 365) +-#define leapyear(year) ((year) % 4 == 0) +-#define days_in_year(a) (leapyear(a) ? 366 : 365) +-#define days_in_month(a) (month_days[(a) - 1]) +- +-static int month_days[12] = { +- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +-}; +- +-/* +- * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) +- */ +-void +-GregorianDay(struct local_rtc_time * tm) +-{ +- int leapsToDate; +- int lastYear; +- int day; +- int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; +- +- lastYear=tm->tm_year-1; +- +- /* +- * Number of leap corrections to apply up to end of last year +- */ +- leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; +- +- /* +- * This year is a leap year if it is divisible by 4 except when it is +- * divisible by 100 unless it is divisible by 400 +- * +- * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be +- */ +- if((tm->tm_year%4==0) && +- ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && +- (tm->tm_mon>2)) +- { +- /* +- * We are past Feb. 29 in a leap year +- */ +- day=1; +- } +- else +- { +- day=0; +- } +- +- day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + +- tm->tm_mday; +- +- tm->tm_wday=day%7; +-} +- +-void +-to_tm(int tim, struct local_rtc_time * tm) +-{ +- register int i; +- register long hms, day; +- +- day = tim / SECDAY; +- hms = tim % SECDAY; +- +- /* Hours, minutes, seconds are easy */ +- tm->tm_hour = hms / 3600; +- tm->tm_min = (hms % 3600) / 60; +- tm->tm_sec = (hms % 3600) % 60; +- +- /* Number of years in days */ +- for (i = STARTOFTIME; day >= days_in_year(i); i++) +- day -= days_in_year(i); +- tm->tm_year = i; +- +- /* Number of months in days left */ +- if (leapyear(tm->tm_year)) +- days_in_month(FEBRUARY) = 29; +- for (i = 1; day >= days_in_month(i); i++) +- day -= days_in_month(i); +- days_in_month(FEBRUARY) = 28; +- tm->tm_mon = i; +- +- /* Days are what is left over (+1) from all that. */ +- tm->tm_mday = day + 1; +- +- /* +- * Determine the day of week +- */ +- GregorianDay(tm); +-} +- +-char * +-ctime_r(time_t *clock, char *buf) +-{ +- struct local_rtc_time tm; +- static char *DAYOFWEEK[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; +- static char *MONTHOFYEAR[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; +- +- to_tm(*clock, &tm); +- +- sprintf(buf, "%s %s %d %d:%02d:%02d %d", DAYOFWEEK[tm.tm_wday], MONTHOFYEAR[tm.tm_mon-1], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year); +- return(buf); +-} +- +- +-#ifdef CONFIG_KDB +- +-int +-NO_TRACE +-profile_dump_tasklist(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +- Scope_Dump_Tasklist(); +- return( 0 ); +-} +- +-int +-NO_TRACE +-profile_dump_scopetable(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +- Scope_Dump_Scopetable(); +- return( 0 ); +-} +- +-int +-NO_TRACE +-profile_dump_daemonque(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +- Daemon_Dumpque(); +- return( 0 ); +-} +- +-int +-NO_TRACE +-profile_dump_DbgBuffer(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +- unsigned long offset = DbgPrintBufferReadOffset; +- if (argc > 0) +- { +- if (!strcmp("-r", argv[1])) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- } +- else if (!strcmp("-e", argv[1]) && (argc > 1)) +- { +- offset = simple_strtoul(argv[2], NULL, 0); +- if (offset && offset < DbgPrintBufferOffset) +- { +- offset = DbgPrintBufferOffset - offset; +- } +- else +- { +- offset = DbgPrintBufferOffset; +- } +- } +- else if (!strcmp("-i", argv[1])) +- { +- kdb_printf("DbgPrintBuffer =0x%p\n", DbgPrintBuffer); +- kdb_printf("DbgPrintBufferOffset =0x%lx\n", DbgPrintBufferOffset); +- kdb_printf("DbgPrintBufferSize =0x%lx\n", DbgPrintBufferSize); +- offset = DbgPrintBufferOffset; +- +- } +- } +- while (DbgPrintBufferOffset > offset) +- { +- kdb_printf("%c", DbgPrintBuffer[offset++]); +- } +- return( 0 ); +-} +- +-int +-NO_TRACE +-profile_dump_DentryTree(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +- struct dentry *parent=Novfs_root; +- +- if (argc > 0) +- { +- parent = (void *)simple_strtoul(argv[1], NULL, 0); +- } +- +- if (parent) +- { +- profile_dump_dt(parent, kdb_printf ); +- } +- +- return(0); +-} +- +- +-int +-NO_TRACE +-profile_dump_inode(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +- Novfs_dump_inode( kdb_printf ); +- return( 0 ); +-} +- +-#endif /* CONFIG_KDB */ +- +-typedef struct memory_header +-{ +- struct list_head list; +- void *caller; +- size_t size; +-} MEMORY_LIST, *PMEMORY_LIST; +- +-spinlock_t Malloc_Lock = SPIN_LOCK_UNLOCKED; +-LIST_HEAD( Memory_List ); +- +-void *Novfs_Malloc( size_t size, int flags ) +-{ +- void *p=NULL; +- PMEMORY_LIST mh; +- +- mh = kmalloc(size + sizeof(MEMORY_LIST), flags); +- if (mh) +- { +- mh->caller = __builtin_return_address(0); +- mh->size = size; +- spin_lock(&Malloc_Lock); +- list_add(&mh->list, &Memory_List); +- spin_unlock(&Malloc_Lock); +- p = (char *)mh+sizeof(MEMORY_LIST); +- /*DbgPrint("Novfs_Malloc: 0x%p 0x%p %d\n", p, mh->caller, size); +- */ +- } +- return(p); +-} +- +-void Novfs_Free( const void *p ) +-{ +- PMEMORY_LIST mh; +- +- if (p) +- { +- /*DbgPrint("Novfs_Free: 0x%p 0x%p\n", p, __builtin_return_address(0)); +- */ +- mh = (PMEMORY_LIST)((char *)p-sizeof(MEMORY_LIST)); +- +- spin_lock(&Malloc_Lock); +- list_del(&mh->list); +- spin_unlock(&Malloc_Lock); +- kfree(mh); +- } +-} +- +- +-int +-NO_TRACE +-profile_dump_memorylist_dbg(int argc, const char **argv, const char **envp, struct pt_regs *regs) +-{ +-#ifdef CONFIG_KDB +- profile_dump_memorylist(kdb_printf); +-#endif /* CONFIG_KDB */ +- +- return( 0 ); +-} +- +-void +-NO_TRACE +-profile_dump_memorylist( void *pf ) +-{ +- void (*pfunc)(char *Fmt, ...) = pf; +- +- PMEMORY_LIST mh; +- struct list_head *l; +- +- size_t total=0; +- int count=0; +- +- spin_lock( &Malloc_Lock ); +- +- list_for_each( l, &Memory_List ) +- { +- mh = list_entry(l, MEMORY_LIST, list); +- pfunc("0x%p 0x%p 0x%p %d\n", mh, (char *)mh+sizeof(MEMORY_LIST), mh->caller, mh->size); +- count++; +- total += mh->size; +- } +- spin_unlock( &Malloc_Lock ); +- +- pfunc("Blocks=%d Total=%d\n", count, total); +-} +- +-void +-NO_TRACE +-profile_dump_dt(struct dentry *parent, void *pf ) +-{ +- void (*pfunc)(char *Fmt, ...) = pf; +- struct l { +- struct l *next; +- struct dentry *dentry; +- } *l, *n, *start; +- struct list_head *p; +- struct dentry *d; +- char *buf, *path, *sd; +- char inode_number[16]; +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- +- if( NULL == buf ) +- { +- return; +- } +- +- if (parent) +- { +- pfunc("starting 0x%p %.*s\n", parent, parent->d_name.len, parent->d_name.name); +- if (parent->d_subdirs.next == &parent->d_subdirs) +- { +- pfunc("No children...\n"); +- } +- else +- { +- start = Novfs_Malloc(sizeof(*start), GFP_KERNEL); +- if (start) +- { +- start->next = NULL; +- start->dentry = parent; +- l = start; +- while(l) +- { +- p = l->dentry->d_subdirs.next; +- while(p != &l->dentry->d_subdirs) +- { +- d = list_entry(p, struct dentry, D_CHILD); +- p = p->next; +- +- if (d->d_subdirs.next != &d->d_subdirs) +- { +- n = Novfs_Malloc(sizeof(*n), GFP_KERNEL); +- if (n) +- { +- n->next = l->next; +- l->next = n; +- n->dentry = d; +- } +- } +- else +- { +- path = Scope_dget_path(d, buf, PATH_LENGTH_BUFFER, 1); +- if (path) +- { +- pfunc("1-0x%p %s\n" \ +- " d_name: %.*s\n" \ +- " d_parent: 0x%p\n" \ +- " d_count: %d\n" \ +- " d_flags: 0x%x\n" \ +- " d_subdirs: 0x%p\n" \ +- " d_inode: 0x%p\n", +- d, path, d->d_name.len, d->d_name.name, d->d_parent, +- atomic_read(&d->d_count), d->d_flags, d->d_subdirs.next, d->d_inode); +- } +- } +- } +- l = l->next; +- } +- l = start; +- while(l) +- { +- d=l->dentry; +- path = Scope_dget_path(d, buf, PATH_LENGTH_BUFFER, 1); +- if (path) +- { +- sd = " (None)"; +- if (&d->d_subdirs != d->d_subdirs.next) +- { +- sd = ""; +- } +- inode_number[0] = '\0'; +- if (d->d_inode) +- { +- sprintf(inode_number, " (%lu)", d->d_inode->i_ino); +- } +- pfunc("0x%p %s\n" \ +- " d_parent: 0x%p\n" \ +- " d_count: %d\n" \ +- " d_flags: 0x%x\n" \ +- " d_subdirs: 0x%p%s\n" \ +- " d_inode: 0x%p%s\n", +- d, path, d->d_parent, +- atomic_read(&d->d_count), d->d_flags, d->d_subdirs.next, sd, d->d_inode, inode_number); +- } +- +- n = l; +- l = l->next; +- Novfs_Free(n); +- } +- } +- } +- } +- +- Novfs_Free(buf); +- +-} +- +-/*int profile_inode_open(struct inode *inode, struct file *file) +-{ +- +-} +- +-int profile_inode_close(struct inode *inode, struct file *file) +-{ +-} +-*/ +-ssize_t profile_common_read( char *buf, size_t len, loff_t *off ) +-{ +- ssize_t retval=0; +- size_t count; +- unsigned long offset = *off; +- +- if (0 != (count = DbgPrintBufferOffset - offset)) +- { +- if (count > len) +- { +- count = len; +- } +- +- count -= copy_to_user(buf, &DbgPrintBuffer[offset], count); +- +- if (count == 0) +- { +- retval = -EFAULT; +- } +- else +- { +- *off += (loff_t)count; +- retval = count; +- } +- } +- return retval; +- +-} +- +-//ssize_t NO_TRACE profile_inode_read(struct file *file, char *buf, size_t len, loff_t *off) +-ssize_t profile_inode_read(struct file *file, char *buf, size_t len, loff_t *off) +-{ +- ssize_t retval=0; +- unsigned long offset = *off; +- static char save_DbgPrintOn; +- +- if (offset == 0) +- { +- down(&LocalPrint_lock); +- save_DbgPrintOn = DbgPrintOn; +- DbgPrintOn = 0; +- +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- Novfs_dump_inode( LocalPrint ); +- } +- +- retval = profile_common_read(buf, len, off); +- +- if ( 0 == retval) +- { +- DbgPrintOn = save_DbgPrintOn; +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- +- up(&LocalPrint_lock); +- } +- +- return retval; +- +-} +- +-ssize_t NO_TRACE profile_dentry_read(struct file *file, char *buf, size_t len, loff_t *off) +-{ +- ssize_t retval=0; +- unsigned long offset = *off; +- static char save_DbgPrintOn; +- +- if (offset == 0) +- { +- down(&LocalPrint_lock); +- save_DbgPrintOn = DbgPrintOn; +- DbgPrintOn = 0; +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- profile_dump_dt(Novfs_root, LocalPrint); +- } +- +- retval = profile_common_read(buf, len, off); +- +- if ( 0 == retval) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- DbgPrintOn = save_DbgPrintOn; +- +- up(&LocalPrint_lock); +- } +- +- return retval; +- +-} +- +-ssize_t NO_TRACE profile_memory_read(struct file *file, char *buf, size_t len, loff_t *off) +-{ +- ssize_t retval=0; +- unsigned long offset = *off; +- static char save_DbgPrintOn; +- +- if (offset == 0) +- { +- down(&LocalPrint_lock); +- save_DbgPrintOn = DbgPrintOn; +- DbgPrintOn = 0; +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- profile_dump_memorylist( LocalPrint ); +- } +- +- retval = profile_common_read(buf, len, off); +- +- if ( 0 == retval) +- { +- DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; +- DbgPrintOn = save_DbgPrintOn; +- +- up(&LocalPrint_lock); +- } +- +- return retval; +- +-} +diff -uNr src.old/novfs/profile_funcs.h src/novfs/profile_funcs.h +--- src.old/novfs/profile_funcs.h 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/profile_funcs.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,419 +0,0 @@ +-extern void Daemon_Added_Resource( void ); +-extern void Daemon_Close_Control( void ); +-extern void Daemon_CreateSessionId( void ); +-extern void Daemon_DestroySessionId( void ); +-extern void Daemon_Dumpque( void ); +-extern void Daemon_Get_UserSpace( void ); +-extern void Daemon_Library_close( void ); +-extern void Daemon_Library_ioctl( void ); +-extern void Daemon_Library_open( void ); +-extern void Daemon_Library_read( void ); +-extern void Daemon_Library_write( void ); +-extern void Daemon_Login( void ); +-extern void Daemon_Logout( void ); +-extern void Daemon_Open_Control( void ); +-extern void Daemon_Poll( void ); +-extern void Daemon_Receive_Reply( void ); +-extern void Daemon_Remove_Resource( void ); +-extern void Daemon_Send_Command( void ); +-extern void Daemon_SetMountPoint( void ); +-extern void Daemon_Timer( void ); +-extern void Daemon_getpwuid( void ); +-extern void Daemon_getversion( void ); +-extern void Daemon_ioctl( void ); +-extern void GetConnData( void ); +-extern void GetUserData( void ); +-extern void Init_Daemon_Queue( void ); +-extern void Init_Procfs_Interface( void ); +-extern void Novfs_Add_to_Root( void ); +-extern void Novfs_Add_to_Root2( void ); +-extern void Novfs_Close_File( void ); +-extern void Novfs_Close_Stream( void ); +-extern void Novfs_Control_ioctl( void ); +-extern void Novfs_Control_read( void ); +-extern void Novfs_Control_write( void ); +-extern void Novfs_Create( void ); +-extern void Novfs_Delete( void ); +-extern void Novfs_Find_Name_In_List( void ); +-extern void Novfs_Get_Connected_Server_List( void ); +-extern void Novfs_Get_Directory_List( void ); +-extern void Novfs_Get_Directory_ListEx( void ); +-extern void Novfs_Get_File_Info( void ); +-extern void Novfs_Get_File_Info2( void ); +-extern void Novfs_Get_Server_Volume_List( void ); +-extern void Novfs_Get_Version( void ); +-extern void Novfs_Open_File( void ); +-extern void Novfs_Read_File( void ); +-extern void Novfs_Read_Stream( void ); +-extern void Novfs_Remove_from_Root( void ); +-extern void Novfs_Rename_File( void ); +-extern void Novfs_Set_Attr( void ); +-extern void Novfs_Truncate_File( void ); +-extern void Novfs_User_proc_ioctl( void ); +-extern void Novfs_User_proc_read( void ); +-extern void Novfs_User_proc_write( void ); +-extern void Novfs_Verify_Server_Name( void ); +-extern void Novfs_Verify_Volume_Name( void ); +-extern void Novfs_Write_File( void ); +-extern void Novfs_Write_File2( void ); +-extern void Novfs_Write_Stream( void ); +-extern void Novfs_a_readpage( void ); +-extern void Novfs_add_inode_entry( void ); +-extern void Novfs_clear_inode( void ); +-extern void Novfs_d_add( void ); +-extern void Novfs_d_compare( void ); +-extern void Novfs_d_delete( void ); +-extern void Novfs_d_hash( void ); +-extern void Novfs_d_iput( void ); +-extern void Novfs_d_lookup( void ); +-extern void Novfs_d_release( void ); +-extern void Novfs_d_revalidate( void ); +-extern void Novfs_d_strcmp( void ); +-extern void Novfs_dget_path( void ); +-extern void Novfs_dir_fsync( void ); +-extern void Novfs_dir_lseek( void ); +-extern void Novfs_dir_open( void ); +-extern void Novfs_dir_read( void ); +-extern void Novfs_dir_readdir( void ); +-extern void Novfs_dir_release( void ); +-extern void Novfs_enumerate_inode_cache( void ); +-extern void Novfs_f_flush( void ); +-extern void Novfs_f_fsync( void ); +-extern void Novfs_f_ioctl( void ); +-extern void Novfs_f_llseek( void ); +-extern void Novfs_f_lock( void ); +-extern void Novfs_f_mmap( void ); +-extern void Novfs_f_open( void ); +-extern void Novfs_f_read( void ); +-extern void Novfs_f_readdir( void ); +-extern void Novfs_f_release( void ); +-extern void Novfs_f_write( void ); +-extern void Novfs_fill_super( void ); +-extern void Novfs_free_inode_cache( void ); +-extern void Novfs_free_invalid_entries( void ); +-extern void Novfs_get_alltrees( void ); +-extern void Novfs_get_entry( void ); +-extern void Novfs_get_entry_time( void ); +-extern void Novfs_get_inode( void ); +-extern void Novfs_get_remove_entry( void ); +-extern void Novfs_get_sb( void ); +-extern void Novfs_i_create( void ); +-extern void Novfs_i_getattr( void ); +-extern void Novfs_i_lookup( void ); +-extern void Novfs_i_mkdir( void ); +-extern void Novfs_i_mknod( void ); +-extern void Novfs_i_permission( void ); +-extern void Novfs_i_rename( void ); +-extern void Novfs_i_revalidate( void ); +-extern void Novfs_i_rmdir( void ); +-extern void Novfs_i_setattr( void ); +-extern void Novfs_i_unlink( void ); +-extern void Novfs_internal_hash( void ); +-extern void Novfs_invalidate_inode_cache( void ); +-extern void Novfs_kill_sb( void ); +-extern void Novfs_lock_inode_cache( void ); +-extern void Novfs_lookup_inode_cache( void ); +-extern void Novfs_lookup_validate( void ); +-extern void Novfs_notify_change( void ); +-extern void Novfs_read_inode( void ); +-extern void Novfs_remove_inode_entry( void ); +-extern void Novfs_show_options( void ); +-extern void Novfs_statfs( void ); +-extern void Novfs_tree_read( void ); +-extern void Novfs_unlock_inode_cache( void ); +-extern void Novfs_update_entry( void ); +-extern void Novfs_verify_file( void ); +-extern void Novfs_write_inode( void ); +-extern void NwAuthConnWithId( void ); +-extern void NwConnClose( void ); +-extern void NwGetConnInfo( void ); +-extern void NwGetDaemonVersion( void ); +-extern void NwGetIdentityInfo( void ); +-extern void NwLicenseConn( void ); +-extern void NwLoginIdentity( void ); +-extern void NwLogoutIdentity( void ); +-extern void NwOpenConnByAddr( void ); +-extern void NwOpenConnByName( void ); +-extern void NwOpenConnByRef( void ); +-extern void NwQueryFeature( void ); +-extern void NwRawSend( void ); +-extern void NwScanConnInfo( void ); +-extern void NwSetConnInfo( void ); +-extern void NwSysConnClose( void ); +-extern void NwUnAuthenticate( void ); +-extern void NwUnlicenseConn( void ); +-extern void NwcChangeAuthKey( void ); +-extern void NwcEnumIdentities( void ); +-extern void NwcEnumerateDrives( void ); +-extern void NwcGetBroadcastMessage( void ); +-extern void NwcGetDefaultNameCtx( void ); +-extern void NwcGetPreferredDSTree( void ); +-extern void NwcGetPrimaryConn( void ); +-extern void NwcGetTreeMonitoredConn( void ); +-extern void NwcSetDefaultNameCtx( void ); +-extern void NwcSetMapDrive( void ); +-extern void NwcSetPreferredDSTree( void ); +-extern void NwcSetPrimaryConn( void ); +-extern void NwcUnMapDrive( void ); +-extern void NwdConvertLocalHandle( void ); +-extern void NwdConvertNetwareHandle( void ); +-extern void NwdGetMountPath( void ); +-extern void NwdSetKeyValue( void ); +-extern void NwdSetMapDrive( void ); +-extern void NwdUnMapDrive( void ); +-extern void NwdVerifyKeyValue( void ); +-extern void Queue_Daemon_Command( void ); +-extern void Queue_get( void ); +-extern void Queue_put( void ); +-extern void RemoveDriveMaps( void ); +-extern void Scope_Cleanup( void ); +-extern void Scope_Cleanup_Thread( void ); +-extern void Scope_Dump_Scopetable( void ); +-extern void Scope_Dump_Tasklist( void ); +-extern void Scope_Find_Scope( void ); +-extern void Scope_Get_Hash( void ); +-extern void Scope_Get_ScopeUsers( void ); +-extern void Scope_Get_ScopefromName( void ); +-extern void Scope_Get_ScopefromPath( void ); +-extern void Scope_Get_SessionId( void ); +-extern void Scope_Get_Uid( void ); +-extern void Scope_Get_UserName( void ); +-extern void Scope_Get_UserSpace( void ); +-extern void Scope_Init( void ); +-extern void Scope_Lookup( void ); +-extern void Scope_Search4Scope( void ); +-extern void Scope_Set_UserSpace( void ); +-extern void Scope_Timer_Function( void ); +-extern void Scope_Uninit( void ); +-extern void Scope_Validate_Scope( void ); +-extern void Uninit_Daemon_Queue( void ); +-extern void Uninit_Procfs_Interface( void ); +-extern void add_to_list( void ); +-extern void begin_directory_enumerate( void ); +-extern void directory_enumerate( void ); +-extern void directory_enumerate_ex( void ); +-extern void do_login( void ); +-extern void do_logout( void ); +-extern void end_directory_enumerate( void ); +-extern void exit_novfs( void ); +-extern void find_queue( void ); +-extern void get_next_queue( void ); +-extern void init_novfs( void ); +-extern void local_unlink( void ); +-extern void process_list( void ); +-extern void update_inode( void ); +-extern void verify_dentry( void ); +- +-SYMBOL_TABLE SymbolTable[] = { +- {Scope_Get_UserSpace, "Scope_Get_UserSpace"}, +- {NwLoginIdentity, "NwLoginIdentity"}, +- {Novfs_d_revalidate, "Novfs_d_revalidate"}, +- {Daemon_SetMountPoint, "Daemon_SetMountPoint"}, +- {Scope_Get_Hash, "Scope_Get_Hash"}, +- {Queue_get, "Queue_get"}, +- {Queue_Daemon_Command, "Queue_Daemon_Command"}, +- {Novfs_dir_fsync, "Novfs_dir_fsync"}, +- {Novfs_Read_File, "Novfs_Read_File"}, +- {Daemon_Library_close, "Daemon_Library_close"}, +- {NwRawSend, "NwRawSend"}, +- {Novfs_get_inode, "Novfs_get_inode"}, +- {Novfs_Remove_from_Root, "Novfs_Remove_from_Root"}, +- {Novfs_Find_Name_In_List, "Novfs_Find_Name_In_List"}, +- {Scope_Get_SessionId, "Scope_Get_SessionId"}, +- {NwOpenConnByAddr, "NwOpenConnByAddr"}, +- {Novfs_read_inode, "Novfs_read_inode"}, +- {Novfs_Truncate_File, "Novfs_Truncate_File"}, +- {Daemon_Login, "Daemon_Login"}, +- {Scope_Get_ScopefromPath, "Scope_Get_ScopefromPath"}, +- {NwcGetTreeMonitoredConn, "NwcGetTreeMonitoredConn"}, +- {Novfs_write_inode, "Novfs_write_inode"}, +- {Scope_Lookup, "Scope_Lookup"}, +- {NwQueryFeature, "NwQueryFeature"}, +- {Novfs_get_entry_time, "Novfs_get_entry_time"}, +- {Novfs_Control_write, "Novfs_Control_write"}, +- {Scope_Get_Uid, "Scope_Get_Uid"}, +- {NwSysConnClose, "NwSysConnClose"}, +- {NwConnClose, "NwConnClose"}, +- {Novfs_get_entry, "Novfs_get_entry"}, +- {Novfs_Rename_File, "Novfs_Rename_File"}, +- {NwdConvertLocalHandle, "NwdConvertLocalHandle"}, +- {Novfs_dir_lseek, "Novfs_dir_lseek"}, +- {Scope_Get_ScopefromName, "Scope_Get_ScopefromName"}, +- {NwcGetPrimaryConn, "NwcGetPrimaryConn"}, +- {Novfs_d_strcmp, "Novfs_d_strcmp"}, +- {Daemon_Library_ioctl, "Daemon_Library_ioctl"}, +- {end_directory_enumerate, "end_directory_enumerate"}, +- {directory_enumerate, "directory_enumerate"}, +- {begin_directory_enumerate, "begin_directory_enumerate"}, +- {NwdGetMountPath, "NwdGetMountPath"}, +- {NwAuthConnWithId, "NwAuthConnWithId"}, +- {Novfs_Set_Attr, "Novfs_Set_Attr"}, +- {Daemon_getversion, "Daemon_getversion"}, +- {Scope_Dump_Scopetable, "Scope_Dump_Scopetable"}, +- {NwcSetMapDrive, "NwcSetMapDrive"}, +- {Novfs_lookup_inode_cache, "Novfs_lookup_inode_cache"}, +- {Novfs_i_mkdir, "Novfs_i_mkdir"}, +- {Novfs_free_invalid_entries, "Novfs_free_invalid_entries"}, +- {Novfs_dump_inode_cache, "Novfs_dump_inode_cache"}, +- {Novfs_Write_Stream, "Novfs_Write_Stream"}, +- {Novfs_Verify_Server_Name, "Novfs_Verify_Server_Name"}, +- {GetConnData, "GetConnData"}, +- {Uninit_Procfs_Interface, "Uninit_Procfs_Interface"}, +- {Scope_Validate_Scope, "Scope_Validate_Scope"}, +- {Scope_Timer_Function, "Scope_Timer_Function"}, +- {Novfs_i_setattr, "Novfs_i_setattr"}, +- {Novfs_i_mknod, "Novfs_i_mknod"}, +- {Novfs_Verify_Volume_Name, "Novfs_Verify_Volume_Name"}, +- {Novfs_Close_Stream, "Novfs_Close_Stream"}, +- {Novfs_Add_to_Root, "Novfs_Add_to_Root"}, +- {Init_Procfs_Interface, "Init_Procfs_Interface"}, +- {Novfs_dump_inode, "Novfs_dump_inode"}, +- {Novfs_Get_Directory_List, "Novfs_Get_Directory_List"}, +- {Novfs_Get_Connected_Server_List, "Novfs_Get_Connected_Server_List"}, +- {Daemon_Logout, "Daemon_Logout"}, +- {do_logout, "do_logout"}, +- {Scope_Search4Scope, "Scope_Search4Scope"}, +- {NwdUnMapDrive, "NwdUnMapDrive"}, +- {Novfs_Control_read, "Novfs_Control_read"}, +- {Scope_Cleanup_Thread, "Scope_Cleanup_Thread"}, +- {Novfs_invalidate_inode_cache, "Novfs_invalidate_inode_cache"}, +- {Novfs_f_flush, "Novfs_f_flush"}, +- {Novfs_enumerate_inode_cache, "Novfs_enumerate_inode_cache"}, +- {Novfs_d_compare, "Novfs_d_compare"}, +- {Daemon_Library_write, "Daemon_Library_write"}, +- {GetUserData, "GetUserData"}, +- {Daemon_Remove_Resource, "Daemon_Remove_Resource"}, +- {Scope_Set_UserSpace, "Scope_Set_UserSpace"}, +- {Novfs_get_alltrees, "Novfs_get_alltrees"}, +- {Daemon_Get_UserSpace, "Daemon_Get_UserSpace"}, +- {Uninit_Daemon_Queue, "Uninit_Daemon_Queue"}, +- {NwcChangeAuthKey, "NwcChangeAuthKey"}, +- {NwLicenseConn, "NwLicenseConn"}, +- {Init_Daemon_Queue, "Init_Daemon_Queue"}, +- {Novfs_tree_read, "Novfs_tree_read"}, +- {Novfs_f_llseek, "Novfs_f_llseek"}, +- {find_queue, "find_queue"}, +- {Scope_Find_Scope, "Scope_Find_Scope"}, +- {Novfs_lookup_validate, "Novfs_lookup_validate"}, +- {Novfs_d_hash, "Novfs_d_hash"}, +- {Novfs_a_readpage, "Novfs_a_readpage"}, +- {Novfs_Create, "Novfs_Create"}, +- {Novfs_Close_File, "Novfs_Close_File"}, +- {Daemon_getpwuid, "Daemon_getpwuid"}, +- {Daemon_CreateSessionId, "Daemon_CreateSessionId"}, +- {Scope_dget_path, "Scope_dget_path"}, +- {NwcSetDefaultNameCtx, "NwcSetDefaultNameCtx"}, +- {NwcGetDefaultNameCtx, "NwcGetDefaultNameCtx"}, +- {NwUnAuthenticate, "NwUnAuthenticate"}, +- {Novfs_i_getattr, "Novfs_i_getattr"}, +- {Novfs_get_remove_entry, "Novfs_get_remove_entry"}, +- {Novfs_f_ioctl, "Novfs_f_ioctl"}, +- {Scope_Get_ScopeUsers, "Scope_Get_ScopeUsers"}, +- {Scope_Dump_Tasklist, "Scope_Dump_Tasklist"}, +- {NwOpenConnByRef, "NwOpenConnByRef"}, +- {Novfs_unlock_inode_cache, "Novfs_unlock_inode_cache"}, +- {Novfs_lock_inode_cache, "Novfs_lock_inode_cache"}, +- {Daemon_DestroySessionId, "Daemon_DestroySessionId"}, +- {do_login, "do_login"}, +- {Novfs_free_inode_cache, "Novfs_free_inode_cache"}, +- {Novfs_Read_Stream, "Novfs_Read_Stream"}, +- {Daemon_Library_read, "Daemon_Library_read"}, +- {NwdSetMapDrive, "NwdSetMapDrive"}, +- {Novfs_internal_hash, "Novfs_internal_hash"}, +- {Daemon_Receive_Reply, "Daemon_Receive_Reply"}, +- {Daemon_Library_open, "Daemon_Library_open"}, +- {get_next_queue, "get_next_queue"}, +- {exit_novfs, "exit_novfs"}, +- {NwcGetBroadcastMessage, "NwcGetBroadcastMessage"}, +- {Novfs_d_lookup, "Novfs_d_lookup"}, +- {Novfs_clear_inode, "Novfs_clear_inode"}, +- {Daemon_Open_Control, "Daemon_Open_Control"}, +- {NwdConvertNetwareHandle, "NwdConvertNetwareHandle"}, +- {NwcUnMapDrive, "NwcUnMapDrive"}, +- {Novfs_notify_change, "Novfs_notify_change"}, +- {Novfs_dir_release, "Novfs_dir_release"}, +- {directory_enumerate_ex, "directory_enumerate_ex"}, +- {RemoveDriveMaps, "RemoveDriveMaps"}, +- {NwOpenConnByName, "NwOpenConnByName"}, +- {Novfs_verify_file, "Novfs_verify_file"}, +- {Novfs_statfs, "Novfs_statfs"}, +- {Novfs_f_write, "Novfs_f_write"}, +- {Novfs_Get_File_Info, "Novfs_Get_File_Info"}, +- {Novfs_Delete, "Novfs_Delete"}, +- {update_inode, "update_inode"}, +- {NwcSetPreferredDSTree, "NwcSetPreferredDSTree"}, +- {NwcGetPreferredDSTree, "NwcGetPreferredDSTree"}, +- {Novfs_update_entry, "Novfs_update_entry"}, +- {Novfs_kill_sb, "Novfs_kill_sb"}, +- {Daemon_ioctl, "Daemon_ioctl"}, +- {Scope_Get_UserName, "Scope_Get_UserName"}, +- {NwcEnumerateDrives, "NwcEnumerateDrives"}, +- {Novfs_i_revalidate, "Novfs_i_revalidate"}, +- {Novfs_f_release, "Novfs_f_release"}, +- {Novfs_f_read, "Novfs_f_read"}, +- {Novfs_d_delete, "Novfs_d_delete"}, +- {Novfs_Write_File, "Novfs_Write_File"}, +- {Novfs_User_proc_ioctl, "Novfs_User_proc_ioctl"}, +- {Novfs_Get_File_Info2, "Novfs_Get_File_Info2"}, +- {NwdSetKeyValue, "NwdSetKeyValue"}, +- {Novfs_remove_inode_entry, "Novfs_remove_inode_entry"}, +- {Novfs_i_rename, "Novfs_i_rename"}, +- {Novfs_f_open, "Novfs_f_open"}, +- {Novfs_d_iput, "Novfs_d_iput"}, +- {Novfs_Get_Directory_ListEx, "Novfs_Get_Directory_ListEx"}, +- {Daemon_Timer, "Daemon_Timer"}, +- {Daemon_Close_Control, "Daemon_Close_Control"}, +- {verify_dentry, "verify_dentry"}, +- {process_list, "process_list"}, +- {local_unlink, "local_unlink"}, +- {init_novfs, "init_novfs"}, +- {NwUnlicenseConn, "NwUnlicenseConn"}, +- {NwGetConnInfo, "NwGetConnInfo"}, +- {Novfs_i_permission, "Novfs_i_permission"}, +- {Novfs_dir_read, "Novfs_dir_read"}, +- {NwcSetPrimaryConn, "NwcSetPrimaryConn"}, +- {Novfs_f_lock, "Novfs_f_lock"}, +- {Novfs_dir_readdir, "Novfs_dir_readdir"}, +- {Novfs_dir_open, "Novfs_dir_open"}, +- {Queue_put, "Queue_put"}, +- {NwLogoutIdentity, "NwLogoutIdentity"}, +- {NwGetIdentityInfo, "NwGetIdentityInfo"}, +- {Novfs_i_rmdir, "Novfs_i_rmdir"}, +- {Novfs_i_create, "Novfs_i_create"}, +- {Novfs_f_mmap, "Novfs_f_mmap"}, +- {Novfs_Write_File2, "Novfs_Write_File2"}, +- {Novfs_User_proc_read, "Novfs_User_proc_read"}, +- {Novfs_show_options, "Novfs_show_options"}, +- {Novfs_add_inode_entry, "Novfs_add_inode_entry"}, +- {Novfs_Open_File, "Novfs_Open_File"}, +- {Novfs_Get_Version, "Novfs_Get_Version"}, +- {Daemon_Poll, "Daemon_Poll"}, +- {add_to_list, "add_to_list"}, +- {Scope_Init, "Scope_Init"}, +- {Scope_Cleanup, "Scope_Cleanup"}, +- {NwSetConnInfo, "NwSetConnInfo"}, +- {Novfs_i_unlink, "Novfs_i_unlink"}, +- {Novfs_get_sb, "Novfs_get_sb"}, +- {Novfs_f_readdir, "Novfs_f_readdir"}, +- {Novfs_f_fsync, "Novfs_f_fsync"}, +- {Novfs_d_release, "Novfs_d_release"}, +- {Novfs_User_proc_write, "Novfs_User_proc_write"}, +- {Daemon_Send_Command, "Daemon_Send_Command"}, +- {Daemon_Dumpque, "Daemon_Dumpque"}, +- {NwcEnumIdentities, "NwcEnumIdentities"}, +- {NwGetDaemonVersion, "NwGetDaemonVersion"}, +- {Novfs_i_lookup, "Novfs_i_lookup"}, +- {Novfs_fill_super, "Novfs_fill_super"}, +- {Novfs_Get_Server_Volume_List, "Novfs_Get_Server_Volume_List"}, +- {Novfs_Add_to_Root2, "Novfs_Add_to_Root2"}, +- {Daemon_SendDebugCmd, "Daemon_SendDebugCmd"}, +- {Daemon_Added_Resource, "Daemon_Added_Resource"}, +- {Scope_Uninit, "Scope_Uninit"}, +- {NwdVerifyKeyValue, "NwdVerifyKeyValue"}, +- {NwScanConnInfo, "NwScanConnInfo"}, +- {Novfs_dget_path, "Novfs_dget_path"}, +- {Novfs_d_add, "Novfs_d_add"}, +- {Novfs_Control_ioctl, "Novfs_Control_ioctl"}, +- // Terminate the table +- {NULL, NULL} +-}; +diff -uNr src.old/novfs/scope.c src/novfs/scope.c +--- src.old/novfs/scope.c 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/scope.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,1210 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: scope.c +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: This module contains functions used to scope +- * users. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +- +-/*===[ Include files specific to Linux ]==================================*/ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/*===[ Include files specific to this module ]============================*/ +-#include "vfs.h" +-#define LEADER signal->leader +- +-/*===[ External data ]====================================================*/ +- +-/*===[ External prototypes ]==============================================*/ +-extern int DbgPrint( char *Fmt, ... ); +-extern int Daemon_CreateSessionId( uint64_t *SessionId ); +-extern int Daemon_DestroySessionId( uint64_t SessionId ); +-extern int Daemon_getpwuid( uid_t uid, int unamelen, char *uname ); +-extern int Daemon_Get_UserSpace( uint64_t SessionId, uint64_t *TotalSize, uint64_t *TotalFree, uint64_t *TotalDirectoryEnties, uint64_t *FreeDirectoryEnties); +- +-extern int Novfs_Remove_from_Root(char *); +-extern int Novfs_Add_to_Root(char *); +- +-/*===[ Manifest constants ]===============================================*/ +-#define CLEANUP_INTERVAL 10 +-#define MAX_USERNAME_LENGTH 32 +- +-/*===[ Type definitions ]=================================================*/ +-typedef struct _SCOPE_LIST_ +-{ +- struct list_head ScopeList; +- scope_t ScopeId; +- session_t SessionId; +- pid_t ScopePid; +- task_t *ScopeTask; +- unsigned long ScopeHash; +- uid_t ScopeUid; +- uint64_t ScopeUSize; +- uint64_t ScopeUFree; +- uint64_t ScopeUTEnties; +- uint64_t ScopeUAEnties; +- int ScopeUserNameLength; +- unsigned char ScopeUserName[MAX_USERNAME_LENGTH]; +-} SCOPE_LIST, *PSCOPE_LIST; +- +-/*===[ Function prototypes ]==============================================*/ +-void Scope_Init( void ); +-void Scope_Uninit( void ); +- +-PSCOPE_LIST Scope_Search4Scope( session_t Id, BOOLEAN Session, BOOLEAN Locked ); +-PSCOPE_LIST Scope_Find_Scope( BOOLEAN Create ); +-unsigned long Scope_Get_Hash( PSCOPE_LIST Scope ); +-uid_t Scope_Get_Uid( PSCOPE_LIST Scope ); +-int Scope_Validate_Scope( PSCOPE_LIST Scope ); +-char *Scope_Get_UserName( PSCOPE_LIST Scope ); +-session_t Scope_Get_SessionId( PSCOPE_LIST Scope ); +-PSCOPE_LIST Scope_Get_ScopefromName( struct qstr *Name ); +-int Scope_Set_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); +-int Scope_Get_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); +- +-char *Scope_Get_ScopeUsers( void ); +-void *Scope_Lookup( void ); +- +-void Scope_Timer_Function(unsigned long Context); +-int Scope_Cleanup_Thread(void *Args); +-void Scope_Cleanup( void ); +-char *Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags); +-void Scope_Dump_Tasklist( void ); +-void Scope_Dump_Scopetable( void ); +- +-/*===[ Global variables ]=================================================*/ +-struct list_head Scope_List; +-struct semaphore Scope_Lock; +-struct semaphore Scope_Thread_Delay; +-int Scope_Thread_Terminate=0; +-struct semaphore Scope_Delay_Event; +-struct timer_list Scope_Timer; +-unsigned long Scope_Hash_Val=1; +- +-/*===[ Code ]=============================================================*/ +- +-/*++======================================================================*/ +-void Scope_Init( void ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- INIT_LIST_HEAD( &Scope_List ); +- init_MUTEX( &Scope_Lock ); +- init_MUTEX_LOCKED( &Scope_Thread_Delay ); +- +-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +- kernel_thread( Scope_Cleanup_Thread, NULL, 0 ); +-#else +- kthread_run(Scope_Cleanup_Thread, NULL, "novfs_ST"); +-#endif +-} +- +-/*++======================================================================*/ +-void Scope_Uninit( void ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- Scope_Thread_Terminate = 1; +- +- up(&Scope_Thread_Delay); +- +- mb(); +- while( Scope_Thread_Terminate ) +- { +- yield(); +- } +- printk( KERN_INFO "Scope_Uninit: Exit\n"); +- +-} +- +-/*++======================================================================*/ +-PSCOPE_LIST Scope_Search4Scope( session_t Id, BOOLEAN Session, BOOLEAN Locked ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope, rscope=NULL; +- struct list_head *sl; +- int offset; +- +- DbgPrint("Scope_Search4Scope: 0x%llx 0x%x 0x%x\n", Id, Session, Locked); +- +- if ( Session ) +- { +- offset = (int)(&((PSCOPE_LIST)0)->SessionId); +- } +- else +- { +- offset = (int)(&((PSCOPE_LIST)0)->ScopeId); +- } +- +- if ( !Locked ) +- { +- down( &Scope_Lock ); +- } +- +- sl = Scope_List.next; +- DbgPrint("Scope_Search4Scope: 0x%x\n", sl); +- while (sl != &Scope_List) +- { +- scope = list_entry(sl, SCOPE_LIST, ScopeList); +- +- if ( Id == *(session_t *)((char *)scope+offset) ) +- { +- rscope = scope; +- break; +- } +- +- sl = sl->next; +- } +- +- if ( !Locked ) +- { +- up( &Scope_Lock ); +- } +- +- DbgPrint("Scope_Search4Scope: return 0x%x\n", rscope); +- return( rscope ); +-} +- +-/*++======================================================================*/ +-PSCOPE_LIST Scope_Find_Scope( BOOLEAN Create ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope=NULL, pscope=NULL; +- task_t *task; +- scope_t scopeId; +- int addscope=0; +- +- task = current; +- +- DbgPrint("Scope_Find_Scope: %d %d %d %d\n", task->uid, task->euid, task->suid, task->fsuid); +- +- scopeId = task->euid; +- +- scope = Scope_Search4Scope( scopeId, FALSE, FALSE ); +- +- if ( !scope && Create ) +- { +- scope = Novfs_Malloc( sizeof(*pscope), GFP_KERNEL ); +- if ( scope ) +- { +- scope->ScopeId = scopeId; +- scope->SessionId = 0; +- scope->ScopePid = task->pid; +- scope->ScopeTask = task; +- scope->ScopeHash = 0; +- scope->ScopeUid = task->euid; +- scope->ScopeUserName[0] = '\0'; +- +- if ( !Daemon_CreateSessionId( &scope->SessionId ) ) +- { +- DbgPrint("Scope_Find_Scope2: %d %d %d %d\n", task->uid, task->euid, task->suid, task->fsuid); +- memset(scope->ScopeUserName, 0, sizeof(scope->ScopeUserName)); +- scope->ScopeUserNameLength = 0; +- Daemon_getpwuid(task->euid, sizeof(scope->ScopeUserName), scope->ScopeUserName); +- scope->ScopeUserNameLength = strlen(scope->ScopeUserName); +- addscope = 1; +- } +- +- scope->ScopeHash = Scope_Hash_Val++; +- DbgPrint("Scope_Find_Scope: Adding 0x%x\n" \ +- " ScopeId: 0x%llx\n" \ +- " SessionId: 0x%llx\n" \ +- " ScopePid: %d\n" \ +- " ScopeTask: 0x%x\n" \ +- " ScopeHash: %d\n" \ +- " ScopeUid: %d\n" \ +- " ScopeUserNameLength: %d\n" \ +- " ScopeUserName: %s\n", +- scope, +- scope->ScopeId, +- scope->SessionId, +- scope->ScopePid, +- scope->ScopeTask, +- scope->ScopeHash, +- scope->ScopeUid, +- scope->ScopeUserNameLength, +- scope->ScopeUserName); +- +- if ( scope->SessionId ) +- { +- down( &Scope_Lock ); +- list_add(&scope->ScopeList, &Scope_List); +- up( &Scope_Lock ); +- } +- else +- { +- Novfs_Free(scope); +- scope = NULL; +- } +- } +- +- if (addscope) +- { +- Novfs_Add_to_Root( scope->ScopeUserName ); +- } +- } +- +- return(scope); +-} +- +-/*++======================================================================*/ +-unsigned long Scope_Get_Hash( PSCOPE_LIST Scope ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- unsigned long hash=0; +- +- if ( NULL == Scope) +- { +- Scope = Scope_Find_Scope( TRUE ); +- } +- +- if ( Scope && Scope_Validate_Scope( Scope )) +- { +- hash = Scope->ScopeHash; +- } +- return( hash ); +-} +- +-/*++======================================================================*/ +-uid_t Scope_Get_Uid( PSCOPE_LIST Scope ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- uid_t uid=0; +- +- if ( NULL == Scope) +- { +- Scope = Scope_Find_Scope( TRUE ); +- } +- +- if ( Scope && Scope_Validate_Scope( Scope )) +- { +- uid = Scope->ScopeUid; +- } +- return( uid ); +-} +- +-/*++======================================================================*/ +-int Scope_Validate_Scope( PSCOPE_LIST Scope ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST s; +- struct list_head *sl; +- int retVal = 0; +- +- DbgPrint("Scope_Validate_Scope: 0x%x\n", Scope); +- +- down( &Scope_Lock ); +- +- sl = Scope_List.next; +- while (sl != &Scope_List) +- { +- s = list_entry(sl, SCOPE_LIST, ScopeList); +- +- if ( s == Scope ) +- { +- retVal = 1; +- break; +- } +- +- sl = sl->next; +- } +- +- up( &Scope_Lock ); +- +- return( retVal ); +-} +- +-/*++======================================================================*/ +-char *Scope_Get_UserName( PSCOPE_LIST Scope ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *name=NULL; +- +- if ( !Scope ) +- { +- Scope = Scope_Find_Scope( TRUE ); +- } +- +- if ( Scope && Scope_Validate_Scope( Scope )) +- { +- name = Scope->ScopeUserName; +- } +- return( name ); +-} +- +-/*++======================================================================*/ +-session_t Scope_Get_SessionId( PSCOPE_LIST Scope ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- session_t sessionId=0; +- +- DbgPrint("Scope_Get_SessionId: 0x%p\n", Scope); +- if ( !Scope ) +- { +- Scope = Scope_Find_Scope( TRUE ); +- } +- +- if ( Scope && Scope_Validate_Scope( Scope )) +- { +- sessionId = Scope->SessionId; +- } +- DbgPrint("Scope_Get_SessionId: return 0x%llx\n", sessionId); +- return( sessionId ); +-} +- +-/*++======================================================================*/ +-PSCOPE_LIST Scope_Get_ScopefromName( struct qstr *Name ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope, rscope=NULL; +- struct list_head *sl; +- +- DbgPrint("Scope_Get_ScopefromName: %.*s\n", Name->len, Name->name); +- +- down( &Scope_Lock ); +- +- sl = Scope_List.next; +- while (sl != &Scope_List) +- { +- scope = list_entry(sl, SCOPE_LIST, ScopeList); +- +- if ( (Name->len == scope->ScopeUserNameLength) && +- (0 == strncmp(scope->ScopeUserName, Name->name, Name->len)) ) +- { +- rscope = scope; +- break; +- } +- +- sl = sl->next; +- } +- +- up( &Scope_Lock ); +- +- return( rscope ); +-} +- +-/*++======================================================================*/ +-int Scope_Set_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope; +- int retVal=0; +- +- scope = Scope_Find_Scope( TRUE ); +- +- if ( scope ) +- { +- if (TotalSize) scope->ScopeUSize = *TotalSize; +- if (Free) scope->ScopeUFree = *Free; +- if (TotalEnties) scope->ScopeUTEnties = *TotalEnties; +- if (FreeEnties) scope->ScopeUAEnties = *FreeEnties; +- } +- +- +- return( retVal ); +-} +- +-/*++======================================================================*/ +-int Scope_Get_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope; +- int retVal=0; +- +- uint64_t td, fd, te, fe; +- +- scope = Scope_Find_Scope( TRUE ); +- +- td = fd = te = fe = 0; +- if ( scope ) +- { +- +- retVal = Daemon_Get_UserSpace(scope->SessionId, &td, &fd, &te, &fe); +- +- scope->ScopeUSize = td; +- scope->ScopeUFree = fd; +- scope->ScopeUTEnties = te; +- scope->ScopeUAEnties = fe; +- } +- +- if (TotalSize) *TotalSize = td; +- if (Free) *Free = fd; +- if (TotalEnties) *TotalEnties = te; +- if (FreeEnties) *FreeEnties = fe; +- +- return( retVal ); +-} +- +-/*++======================================================================*/ +-PSCOPE_LIST Scope_Get_ScopefromPath( struct dentry *Dentry ) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope=NULL; +- char *buf, *path, *cp; +- struct qstr name; +- +- buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +- if (buf) +- { +- path = Scope_dget_path( Dentry, buf, PATH_LENGTH_BUFFER, 0 ); +- if (path) +- { +- DbgPrint("Scope_Get_ScopefromPath: %s\n", path ); +- +- if (*path == '/') path++; +- +- cp = path; +- if ( *cp ) +- { +- while ( *cp && (*cp != '/') ) cp++; +- +- *cp = '\0'; +- name.hash = 0; +- name.len = (int)(cp-path); +- name.name = path; +- scope = Scope_Get_ScopefromName( &name ); +- } +- } +- Novfs_Free(buf); +- } +- +- return( scope ); +-} +- +-/*++======================================================================*/ +-char *add_to_list(char *Name, char *List, char *EndOfList) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- while (*Name && (List < EndOfList) ) +- { +- *List++ = *Name++; +- } +- +- if (List < EndOfList) +- { +- *List++ = '\0'; +- } +- return(List); +-} +- +-/*++======================================================================*/ +-char *Scope_Get_ScopeUsers() +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope; +- struct list_head *sl; +- int asize=8*MAX_USERNAME_LENGTH; +- char *list, *cp, *ep; +- +- DbgPrint("Scope_Get_ScopeUsers\n"); +- +- do /* Copy list until done or out of memory */ +- { +- list = Novfs_Malloc(asize, GFP_KERNEL); +- +- DbgPrint("Scope_Get_ScopeUsers list=0x%p\n", list); +- if (list) +- { +- cp = list; +- ep = cp+asize; +- +- /* +- * Add the tree and server entries +- */ +- cp = add_to_list(TREE_DIRECTORY_NAME, cp, ep); +- cp = add_to_list(SERVER_DIRECTORY_NAME, cp, ep); +- +- down( &Scope_Lock ); +- +- sl = Scope_List.next; +- while ( (sl != &Scope_List) && (cp < ep) ) +- { +- scope = list_entry(sl, SCOPE_LIST, ScopeList); +- +- DbgPrint("Scope_Get_ScopeUsers found 0x%p %s\n", scope, scope->ScopeUserName); +- +- cp = add_to_list(scope->ScopeUserName, cp, ep); +- +- sl = sl->next; +- } +- +- up( &Scope_Lock ); +- +- if (cp < ep) +- { +- *cp++ = '\0'; +- asize = 0; +- } +- else /* Allocation was to small, up size */ +- { +- asize *= 4; +- Novfs_Free(list); +- list=NULL; +- } +- } +- else /* if allocation fails return an empty list */ +- { +- break; +- } +- } while ( !list ); /* List was to small try again */ +- +- return( list ); +-} +- +-/*++======================================================================*/ +-void *Scope_Lookup() +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope; +- +- scope = Scope_Find_Scope( TRUE ); +- return( scope ); +-} +- +-/*++======================================================================*/ +-void +-NO_TRACE +-Scope_Timer_Function(unsigned long Context) +-/* +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- up(&Scope_Thread_Delay); +-} +- +-/*++======================================================================*/ +-int Scope_Cleanup_Thread(void *Args) +-/* +- * +- * Arguments: +- * +- * Returns: +- * +- * Abstract: +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope, rscope; +- struct list_head *sl, cleanup; +- task_t *task; +- +- DbgPrint( "Scope_Cleanup_Thread: %d\n", current->pid); +- +-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +- lock_kernel(); +- snprintf(current->comm, 16, "novfs_ST"); +- unlock_kernel(); +- sys_close(0); +- sys_close(1); +- sys_close(2); +-#endif +- +- /* +- * Setup and start que timer +- */ +- init_timer( &Scope_Timer ); +- +- for ( ;; ) +- { +- DbgPrint( "Scope_Cleanup_Thread: looping\n"); +- if ( Scope_Thread_Terminate ) +- { +- break; +- } +- +- /* +- * Check scope list for any terminated processes +- */ +- down( &Scope_Lock ); +- +- sl = Scope_List.next; +- INIT_LIST_HEAD( &cleanup ); +- +- while (sl != &Scope_List) +- { +- scope = list_entry(sl, SCOPE_LIST, ScopeList); +- sl = sl->next; +- +- rscope = NULL; +- read_lock(&tasklist_lock); +- for_each_process(task) +- { +- if ( (task->uid == scope->ScopeUid) || (task->euid == scope->ScopeUid) ) +- { +- rscope = scope; +- break; +- } +- } +- read_unlock(&tasklist_lock); +- if ( !rscope ) +- { +- list_move( &scope->ScopeList, &cleanup ); +- DbgPrint("Scope_Cleanup_Thread: Scope=0x%x\n", rscope); +- } +- } +- +- up(&Scope_Lock); +- +- sl = cleanup.next; +- while ( sl != &cleanup ) +- { +- scope = list_entry(sl, SCOPE_LIST, ScopeList); +- sl = sl->next; +- +- DbgPrint("Scope_Cleanup_Thread: Removing 0x%x\n" \ +- " ScopeId: 0x%llx\n" \ +- " SessionId: 0x%llx\n" \ +- " ScopePid: %d\n" \ +- " ScopeTask: 0x%x\n" \ +- " ScopeHash: %d\n" \ +- " ScopeUid: %d\n" \ +- " ScopeUserName: %s\n", +- scope, +- scope->ScopeId, +- scope->SessionId, +- scope->ScopePid, +- scope->ScopeTask, +- scope->ScopeHash, +- scope->ScopeUid, +- scope->ScopeUserName); +- if ( !Scope_Search4Scope(scope->SessionId, TRUE, FALSE) ) +- { +- Novfs_Remove_from_Root( scope->ScopeUserName ); +- Daemon_DestroySessionId( scope->SessionId ); +- } +- Novfs_Free( scope ); +- } +- +- Scope_Timer.expires = jiffies + HZ*CLEANUP_INTERVAL; +- Scope_Timer.data = (unsigned long)0; +- Scope_Timer.function = Scope_Timer_Function; +- add_timer(&Scope_Timer); +- DbgPrint( "Scope_Cleanup_Thread: sleeping\n"); +- +- if (down_interruptible( &Scope_Thread_Delay )) +- { +- break; +- } +- del_timer(&Scope_Timer); +- } +- Scope_Thread_Terminate = 0; +- +- printk( KERN_INFO "Scope_Cleanup_Thread: Exit\n"); +- DbgPrint( "Scope_Cleanup_Thread: Exit\n"); +- return(0); +-} +- +-/*++======================================================================*/ +-void Scope_Cleanup( void ) +-/* +- * +- * Arguments: None +- * +- * Returns: Nothing +- * +- * Abstract: Removes all knows scopes. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- PSCOPE_LIST scope; +- struct list_head *sl; +- +- DbgPrint( "Scope_Cleanup:\n"); +- +- /* +- * Check scope list for any terminated processes +- */ +- down( &Scope_Lock ); +- +- sl = Scope_List.next; +- +- while (sl != &Scope_List) +- { +- scope = list_entry( sl, SCOPE_LIST, ScopeList ); +- sl = sl->next; +- +- list_del( &scope->ScopeList ); +- +- DbgPrint("Scope_Cleanup: Removing 0x%x\n" \ +- " ScopeId: 0x%llx\n" \ +- " SessionId: 0x%llx\n" \ +- " ScopePid: %d\n" \ +- " ScopeTask: 0x%x\n" \ +- " ScopeHash: %d\n" \ +- " ScopeUid: %d\n" \ +- " ScopeUserName: %s\n", +- scope, +- scope->ScopeId, +- scope->SessionId, +- scope->ScopePid, +- scope->ScopeTask, +- scope->ScopeHash, +- scope->ScopeUid, +- scope->ScopeUserName); +- if ( !Scope_Search4Scope( scope->SessionId, TRUE, TRUE ) ) +- { +- Novfs_Remove_from_Root( scope->ScopeUserName ); +- Daemon_DestroySessionId( scope->SessionId ); +- } +- Novfs_Free( scope ); +- } +- +- up(&Scope_Lock); +- +-} +- +-/*++======================================================================*/ +-char * +-NO_TRACE +-Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags) +-/* +- * Arguments: struct dentry *Dentry - starting entry +- * char *Buf - pointer to memory buffer +- * unsigned int Buflen - size of memory buffer +- * +- * Returns: pointer to path. +- * +- * Abstract: Walks the dentry chain building a path. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- char *retval=&Buf[Buflen]; +- struct dentry *p=Dentry; +- int len; +- +- *(--retval) = '\0'; +- Buflen--; +- +-/* +- if (!IS_ROOT(p)) +- { +- while (Buflen && !IS_ROOT(p)) +- { +- if (Buflen > p->d_name.len) +- { +- retval -= p->d_name.len; +- Buflen -= p->d_name.len; +- memcpy(retval, p->d_name.name, p->d_name.len); +- *(--retval) = '/'; +- Buflen--; +- p = p->d_parent; +- } +- else +- { +- retval = NULL; +- break; +- } +- } +- } +- if (Flags) +- { +- len = strlen(p->d_sb->s_type->name); +- if (Buflen-len > 0) +- { +- retval -= len; +- Buflen -= len; +- memcpy(retval, p->d_sb->s_type->name, len); +- *(--retval) = '/'; +- Buflen--; +- } +- } +- else +- { +- *(--retval) = '/'; +- Buflen--; +- } +-*/ +- do +- { +- if (Buflen > p->d_name.len) +- { +- retval -= p->d_name.len; +- Buflen -= p->d_name.len; +- memcpy(retval, p->d_name.name, p->d_name.len); +- *(--retval) = '/'; +- Buflen--; +- p = p->d_parent; +- } +- else +- { +- retval = NULL; +- break; +- } +- } while (!IS_ROOT(p)); +- +- if (IS_ROOT(Dentry)) +- { +- retval++; +- } +- +- if (Flags) +- { +- len = strlen(p->d_sb->s_type->name); +- if (Buflen-len > 0) +- { +- retval -= len; +- Buflen -= len; +- memcpy(retval, p->d_sb->s_type->name, len); +- *(--retval) = '/'; +- Buflen--; +- } +- } +- +- return(retval); +-} +- +-void Scope_Dump_Tasklist( void ) +-{ +-#ifdef OLD_DEBUG_KERNEL +- task_t *task; +- struct files_struct *fs; +- int i, open_files=0; +- static char buf[1024]; +- char *path; +- +- +- for_each_process(task) +- { +- kdb_printf("Task List:\n" \ +- " Task: 0x%p\n" \ +- " pid: %d\n" \ +- " tgid: %d\n" \ +- " uid: %d %d %d %d\n" \ +- " gid: %d\n" \ +- " parent: 0x%p\n" \ +- " comm: %s\n" \ +- " user: 0x%p\n" \ +- " real_parent: 0x%p\n" \ +- " parent_exec_id: 0x%x\n" \ +- " self_exec_id: 0x%x\n" \ +- " did_exec: 0x%x\n" \ +- " signal: 0x%p\n" \ +- " thread_info: 0x%p\n" \ +- " security: 0x%p\n", +- task, +- task->pid, +- task->tgid, +- task->uid,task->euid,task->suid,task->fsuid, +- task->gid, +- task->parent, +- task->comm, +- task->user, +- task->real_parent, +- task->parent_exec_id, +- task->self_exec_id, +- task->did_exec, +- task->signal, +- task->thread_info, +- task->security); +- +- fs = task->files; +- kdb_printf(" File List: 0x%p\n", fs); +- if (fs) +- { +- open_files = fs->max_fds; +- kdb_printf(" Max fds: %d\n", open_files); +- for (i = 0; ifd[i]; +- if (f && (f->f_dentry)) +- { +- path = Scope_dget_path(f->f_dentry, buf, sizeof(buf), 1); +- if ( !path ) +- { +- path = buf; +- memcpy(path, f->f_dentry->d_name.name, f->f_dentry->d_name.len); +- path[f->f_dentry->d_name.len] = '\0'; +- } +- kdb_printf(" file(%d): 0x%p\n" \ +- " f_dentry: 0x%p\n" \ +- " d_name: %s\n" \ +- " d_count: %d\n" \ +- " d_inode: 0x%p\n", +- i, f, f->f_dentry, path, +- atomic_read(&f->f_dentry->d_count), +- f->f_dentry->d_inode); +- } +- } +- } +- } +-#endif +-} +- +-void Scope_Dump_Scopetable( void ) +-{ +-#ifdef CONFIG_KDB +- PSCOPE_LIST scope; +- struct list_head *sl; +- +- sl = Scope_List.next; +- while (sl != &Scope_List) +- { +- scope = list_entry(sl, SCOPE_LIST, ScopeList); +- sl = sl->next; +- kdb_printf("Scope List:\n" \ +- " Scope: 0x%p\n" \ +- " ScopeId: 0x%llx\n" \ +- " SessionId: 0x%llx\n" \ +- " ScopePid: %u\n" \ +- " ScopeTask: 0x%p\n" \ +- " ScopeHash: 0x%lx\n" \ +- " ScopeUid: %ld\n" \ +- " ScopeUserName: %s\n", +- scope, +- scope->ScopeId, +- scope->SessionId, +- scope->ScopePid, +- scope->ScopeTask, +- scope->ScopeHash, +- (long)scope->ScopeUid, +- scope->ScopeUserName); +- +- } +- +-#endif +-} +diff -uNr src.old/novfs/vfs.h src/novfs/vfs.h +--- src.old/novfs/vfs.h 2006-07-11 21:24:18.000000000 +0200 ++++ src/novfs/vfs.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,276 +0,0 @@ +-/*++======================================================================== +- * Program Name: Novell NCP Redirector for Linux +- * File Name: vfs.h +- * Version: v1.00 +- * Author: James Turner +- * +- * Abstract: Include module for novfs. +- * Notes: +- * Revision History: +- * +- * +- * Copyright (C) 2005 Novell, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; either version 2 +- * of the License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- *======================================================================--*/ +-#ifndef __STDC_VERSION__ +-#define __STDC_VERSION__ 0L +-#endif +- +-/*===[ Include files specific to Linux ]==================================*/ +-#ifdef CONFIG_KDB +-#include +-#include +- +-#endif /* CONFIG_KDB */ +- +-#include +-#include +- +-/*===[ Include files specific to this module ]============================*/ +- +-/*===[ External data ]====================================================*/ +-extern int Novfs_Version_Major; +-extern int Novfs_Version_Minor; +-extern int Novfs_Version_Sub; +-extern int Novfs_Version_Release; +- +-/*===[ External prototypes ]==============================================*/ +-extern void *Novfs_Malloc( size_t, int ); +-extern void Novfs_Free( const void * ); +- +- +-/*===[ Manifest constants ]===============================================*/ +-#define NOVFS_MAGIC 0x4e574653 +-#define MODULE_NAME "novfs" +- +-#define UNUSED_VARIABLE(a) (a) = (a) +- +-#define TREE_DIRECTORY_NAME ".Trees" +-#define SERVER_DIRECTORY_NAME ".Servers" +- +-#define PATH_LENGTH_BUFFER PATH_MAX +-#define NW_MAX_PATH_LENGTH 255 +- +-#define IOC_LOGIN 0x4a540000 +-#define IOC_LOGOUT 0x4a540001 +-#define IOC_XPLAT 0x4a540002 +-#define IOC_SESSION 0x4a540003 +-#define IOC_DEBUGPRINT 0x4a540004 +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +-#define D_CHILD d_u.d_child +-#else +-#define D_CHILD d_child +-#endif +- +-/* +- * NetWare file attributes +- */ +- +-#define NW_ATTRIBUTE_NORMAL 0x00 +-#define NW_ATTRIBUTE_READ_ONLY 0x01 +-#define NW_ATTRIBUTE_HIDDEN 0x02 +-#define NW_ATTRIBUTE_SYSTEM 0x04 +-#define NW_ATTRIBUTE_EXECUTE_ONLY 0x08 +-#define NW_ATTRIBUTE_DIRECTORY 0x10 +-#define NW_ATTRIBUTE_ARCHIVE 0x20 +-#define NW_ATTRIBUTE_EXECUTE 0x40 +-#define NW_ATTRIBUTE_SHAREABLE 0x80 +- +-/* +- * Define READ/WRITE flag for DATA_LIST +- */ +-#define DLREAD 0 +-#define DLWRITE 1 +- +-/* +- * Define list type +- */ +-#define USER_LIST 1 +-#define SERVER_LIST 2 +-#define VOLUME_LIST 3 +- +-/* +- * Define flags used in for inodes +- */ +-#define USER_INODE 1 +-#define UPDATE_INODE 2 +- +-/* +- * Define flags for directory cache flags +- */ +-#define ENTRY_VALID 0x00000001 +- +-#ifdef INTENT_MAGIC +-#define NDOPENFLAGS intent.it_flags +-#else +-#define NDOPENFLAGS intent.open.flags +-#endif +- +-/* +- * daemon_command_t flags values +- */ +-#define INTERRUPTIBLE 1 +- +-#define NO_TRACE __attribute__((__no_instrument_function__)) +- +-#ifndef NOVFS_VFS_MAJOR +-#define NOVFS_VFS_MAJOR 0 +-#endif +- +-#ifndef NOVFS_VFS_MINOR +-#define NOVFS_VFS_MINOR 0 +-#endif +- +-#ifndef NOVFS_VFS_SUB +-#define NOVFS_VFS_SUB 0 +-#endif +- +-#ifndef NOVFS_VFS_RELEASE +-#define NOVFS_VFS_RELEASE 0 +-#endif +- +-#define VALUE_TO_STR( value ) #value +-#define DEFINE_TO_STR(value) VALUE_TO_STR(value) +- +- +-#define NOVFS_VERSION_STRING \ +- DEFINE_TO_STR(NOVFS_VFS_MAJOR)"." \ +- DEFINE_TO_STR(NOVFS_VFS_MINOR)"." \ +- DEFINE_TO_STR(NOVFS_VFS_SUB)"-" \ +- DEFINE_TO_STR(NOVFS_VFS_RELEASE) +- +-/*===[ Type definitions ]=================================================*/ +-typedef struct _ENTRY_INFO +-{ +- int type; +- umode_t mode; +- uid_t uid; +- gid_t gid; +- loff_t size; +- struct timespec atime; +- struct timespec mtime; +- struct timespec ctime; +- int namelength; +- unsigned char name[1]; +-} ENTRY_INFO, *PENTRY_INFO; +- +-typedef struct _STRING_ +-{ +- int Length; +- unsigned char *Data; +-} STRING, *PSTRING; +- +-typedef struct _LOGIN_ +-{ +- STRING Server; +- STRING UserName; +- STRING Password; +-} LOGIN, *PLOGIN; +- +-typedef struct _LOGOUT_ +-{ +- STRING Server; +-} LOGOUT, *PLOGOUT; +- +-typedef uint64_t scope_t; +-typedef uint64_t session_t; +- +-typedef struct _DIR_CACHE_ +-{ +- struct list_head list; +- int flags; +- u64 jiffies; +- ino_t ino; +- loff_t size; +- umode_t mode; +- struct timespec atime; +- struct timespec mtime; +- struct timespec ctime; +- unsigned long hash; +- int nameLen; +- char name[1]; +-} DIR_CACHE, *PDIR_CACHE; +- +-typedef struct _INODE_DATA_ +-{ +- void *Scope; +- unsigned long Flags; +- struct list_head IList; +- struct inode *Inode; +- struct list_head DirCache; +- struct semaphore DirCacheLock; +- char Name[1]; /* Needs to be last entry */ +-} INODE_DATA, *PINODE_DATA; +- +-typedef struct _DATA_LIST_ +-{ +- void *page; +- void *offset; +- int len; +- int rwflag; +-} DATA_LIST, *PDATA_LIST; +- +-typedef struct _XPLAT_ +-{ +- int xfunction; +- unsigned long reqLen; +- void *reqData; +- unsigned long repLen; +- void *repData; +- +-} XPLAT, *PXPLAT; +- +- +-/*===[ Function prototypes ]==============================================*/ +- +-extern int DbgPrint( char *Fmt, ... ); +-extern char *ctime_r(time_t *clock, char *buf); +- +- +-/*++======================================================================*/ +-static inline unsigned long InterlockedIncrement( unsigned long *p ) +-/* +- * +- * Arguments: unsigned long *p - pointer to value. +- * +- * Returns: unsigned long - value prior to increment. +- * +- * Abstract: The value of *p is incremented and the value of *p before +- * it was incremented is returned. This is an atomic operation. +- * +- * Notes: +- * +- * Environment: +- * +- *========================================================================*/ +-{ +- unsigned long x = 1; +- +- mb(); +- +-#if defined(__i386) || defined(__i386__) +- __asm__ __volatile__( +- " lock xadd %0,(%2)" +- : "+r"(x), "=m"(p) +- : "r"(p), "m"(p) +- : "memory"); +- +-#else +- x = *p++; +-#endif +- return( x ); +-} +diff -uNr src.old/src/Makefile src/src/Makefile +--- src.old/src/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/Makefile 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,58 @@ ++##*++====================================================================== ++## Program Name: Novell NCP Redirector for Linux ++## File Name: Makefile ++## Version: v1.01 ++## Author: James Turner ++## ++## Abstract: This is used to generate the novfs module ++## Notes: ++## Revision History: ++## 6/10/2005 - Added lines for SuSE ++## ++## Copyright (C) 2005 Novell, Inc. ++## ++## This program is free software; you can redistribute it and/or ++## modify it under the terms of the GNU General Public License ++## as published by the Free Software Foundation; either version 2 ++## of the License, or (at your option) any later version. ++## ++## This program is distributed in the hope that it will be useful, ++## but WITHOUT ANY WARRANTY; without even the implied warranty of ++## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++## GNU General Public License for more details. ++## ++## You should have received a copy of the GNU General Public License ++## along with this program; if not, write to the Free Software ++## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++##=====================================================================--*/ ++ ++# ++# Makefile for the Novell NetWare Client for Linux filesystem. ++# ++NOVFS_VFS_MAJOR = 2 ++NOVFS_VFS_MINOR = 0 ++NOVFS_VFS_SUB = 0 ++NOVFS_VFS_RELEASE = 0 ++ ++# Remove # from the following line for debug version ++EXTRA_CFLAGS += -finstrument-functions ++EXTRA_CFLAGS += -g ++EXTRA_CFLAGS += -I. ++EXTRA_CFLAGS += -I$(obj)/../include ++EXTRA_CFLAGS += -I$(obj)/../../include ++EXTRA_CFLAGS += -DNOVFS_VFS_MAJOR=$(NOVFS_VFS_MAJOR) ++EXTRA_CFLAGS += -DNOVFS_VFS_MINOR=$(NOVFS_VFS_MINOR) ++EXTRA_CFLAGS += -DNOVFS_VFS_SUB=$(NOVFS_VFS_SUB) ++EXTRA_CFLAGS += -DNOVFS_VFS_PATCH=$(NOVFS_VFS_PATCH) ++EXTRA_CFLAGS += -DNOVFS_VFS_RELEASE=$(NOVFS_VFS_RELEASE) ++ ++ ++obj-m := novfs.o ++ ++novfs-y := inode.o proc.o profile.o daemon.o file.o scope.o nwcapi.o ++ ++all: ++ make -C /usr/src/linux SUBDIRS=`pwd` modules ++ ++clean: ++ make -C /usr/src/linux SUBDIRS=`pwd` modules clean +diff -uNr src.old/src/blank.c src/src/blank.c +--- src.old/src/blank.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/blank.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,61 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: .c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module ++ * ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++ ++/*===[ Include files specific to this module ]============================*/ ++ ++/*===[ External data ]====================================================*/ ++ ++/*===[ External prototypes ]==============================================*/ ++ ++/*===[ Manifest constants ]===============================================*/ ++ ++/*===[ Type definitions ]=================================================*/ ++ ++/*===[ Function prototypes ]==============================================*/ ++ ++/*===[ Global variables ]=================================================*/ ++ ++/*===[ Code ]=============================================================*/ ++ ++/*++======================================================================*/ ++Function ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ +diff -uNr src.old/src/daemon.c src/src/daemon.c +--- src.old/src/daemon.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/daemon.c 2006-10-16 15:08:23.000000000 +0200 +@@ -0,0 +1,2863 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: daemon.c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module contains all the functions necessary ++ * for sending commands to our daemon module. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/*===[ Include files specific to this module ]============================*/ ++#include "vfs.h" ++#include "nwcapi.h" ++#include "commands.h" ++#include "nwerror.h" ++ ++/*===[ External data ]====================================================*/ ++extern char *Novfs_CurrentMount; ++ ++/*===[ External prototypes ]==============================================*/ ++extern int DbgPrint( char *Fmt, ... ); ++extern void mydump(int size, void *dumpptr); ++ ++extern char *Scope_Get_UserName( void *Scope ); ++extern void *Scope_Lookup( void ); ++extern session_t Scope_Get_SessionId( void *Scope ); ++extern void Scope_Cleanup( void ); ++ ++extern int Novfs_Read_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId); ++extern int Novfs_Write_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); ++extern int Novfs_Close_Stream( u_long ConnHandle, u_char *Handle, session_t SessionId ); ++ ++extern int Novfs_Add_to_Root(char *); ++ ++/* ++ * profile.c functions ++ */ ++extern uint64_t get_nanosecond_time( void ); ++ ++/* ++ * nwcapi.c functions ++ */ ++extern int NwAuthConnWithId(PXPLAT pdata, session_t Session); ++extern int NwConnClose(PXPLAT pdata, u_long *Handle, session_t Session); ++extern int NwGetConnInfo(PXPLAT pdata, session_t Session); ++extern int NwSetConnInfo(PXPLAT pdata, session_t Session); ++extern int NwGetDaemonVersion(PXPLAT pdata, session_t Session); ++extern int NwGetIdentityInfo(PXPLAT pdata, session_t Session); ++extern int NwLicenseConn(PXPLAT pdata, session_t Session); ++extern int NwLoginIdentity(PXPLAT pdata, session_t Session); ++extern int NwLogoutIdentity(PXPLAT pdata, session_t Session); ++extern int NwOpenConnByAddr(PXPLAT pdata, u_long *Handle, session_t Session); ++extern int NwOpenConnByName(PXPLAT pdata, u_long *Handle, session_t Session); ++extern int NwOpenConnByRef(PXPLAT pdata, u_long *Handle, session_t Session); ++extern int NwQueryFeature(PXPLAT pdata, session_t Session); ++extern int NwRawSend(PXPLAT pdata, session_t Session); ++extern int NwScanConnInfo(PXPLAT pdata, session_t Session); ++extern int NwSysConnClose(PXPLAT pdata, u_long *Handle, session_t Session); ++extern int NwUnAuthenticate(PXPLAT pdata, session_t Session); ++extern int NwUnlicenseConn(PXPLAT pdata, session_t Session); ++extern int NwcChangeAuthKey(PXPLAT pdata, session_t Session); ++extern int NwcEnumIdentities(PXPLAT pdata, session_t Session); ++extern int NwcGetDefaultNameCtx(PXPLAT pdata, session_t Session); ++extern int NwcGetPreferredDSTree(PXPLAT pdata, session_t Session); ++extern int NwcGetTreeMonitoredConn(PXPLAT pdata, session_t Session); ++extern int NwcSetDefaultNameCtx(PXPLAT pdata, session_t Session); ++extern int NwcSetPreferredDSTree(PXPLAT pdata, session_t Session); ++extern int NwcSetPrimaryConn(PXPLAT pdata, session_t Session); ++extern int NwcGetPrimaryConn(PXPLAT pdata, session_t Session); ++extern int NwcSetMapDrive(PXPLAT pdata, session_t Session); ++extern int NwcUnMapDrive(PXPLAT pdata, session_t Session); ++extern int NwcEnumerateDrives(PXPLAT pdata, session_t Session); ++extern int NwcGetBroadcastMessage(PXPLAT pdata, session_t Session); ++extern int NwdSetKeyValue(PXPLAT pdata, session_t Session); ++extern int NwdVerifyKeyValue(PXPLAT pdata, session_t Session); ++ ++/*===[ Manifest constants ]===============================================*/ ++#define QUEUE_SENDING 0 ++#define QUEUE_WAITING 1 ++#define QUEUE_TIMEOUT 2 ++#define QUEUE_ACKED 3 ++#define QUEUE_DONE 4 ++ ++#define TIMEOUT_VALUE 10 ++ ++#define DH_TYPE_UNDEFINED 0 ++#define DH_TYPE_STREAM 1 ++#define DH_TYPE_CONNECTION 2 ++ ++/*===[ Type definitions ]=================================================*/ ++typedef struct _DAEMON_QUEUE ++{ ++ struct list_head list; /* Must be first entry */ ++ spinlock_t lock; /* Used to control access to list */ ++ struct semaphore semaphore; /* Used to signal when data is available */ ++} daemon_queue_t; ++ ++typedef struct _DAEMON_COMMAND ++{ ++ struct list_head list; /* Must be first entry */ ++ atomic_t reference; ++ u_long status; ++ u_long flags; ++ struct semaphore semaphore; ++ u_long sequence; ++ struct timer_list timer; ++ void *request; ++ u_long reqlen; ++ void *data; ++ int datalen; ++ void *reply; ++ u_long replen; ++} daemon_command_t; ++ ++ ++typedef struct _DAEMON_HANDLE_ ++{ ++ struct list_head list; ++ rwlock_t lock; ++ session_t session; ++} daemon_handle_t; ++ ++typedef struct _DAEMON_RESOURCE_ ++{ ++ struct list_head list; ++ int type; ++ u_long connection; ++ u_char handle[6]; ++ mode_t mode; ++ loff_t size; ++} daemon_resource_t; ++ ++typedef struct _DRIVE_MAP_ ++{ ++ struct list_head list; /* Must be first item */ ++ session_t session; ++ u_long hash; ++ int namelen; ++ char name[1]; ++} drive_map_t; ++ ++/*===[ Function prototypes ]==============================================*/ ++int Daemon_Added_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_char *FHandle, u_long Mode, u_long Size); ++int Daemon_Close_Control(struct inode *Inode, struct file *File); ++int Daemon_CreateSessionId( uint64_t *SessionId ); ++int Daemon_DestroySessionId( uint64_t SessionId ); ++void Daemon_Dumpque( void ); ++int Daemon_Get_UserSpace( uint64_t SessionId, uint64_t *TotalSize, uint64_t *TotalFree, uint64_t *TotalDirectoryEnties, uint64_t *FreeDirectoryEnties); ++int Daemon_Library_close(struct inode *inode, struct file *file); ++int Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg); ++int Daemon_Library_open(struct inode *inode, struct file *file); ++ssize_t Daemon_Library_read(struct file *file, char *buf, size_t len, loff_t *off); ++ssize_t Daemon_Library_write(struct file *file, const char *buf, size_t len, loff_t *off); ++loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin); ++int Daemon_Login(PLOGIN Login, session_t Session); ++int Daemon_Logout(PLOGOUT Logout, session_t Session); ++int Daemon_Open_Control(struct inode *Inode, struct file *File); ++uint Daemon_Poll(struct file *file, struct poll_table_struct *poll_table); ++ssize_t Daemon_Receive_Reply(struct file * file, char * buf, size_t nbytes, loff_t *ppos); ++int Daemon_Remove_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_long FHandle); ++ ++ssize_t Daemon_Send_Command(struct file *file, char *buf, size_t len, loff_t *off); ++int Daemon_SetMountPoint( char *Path ); ++void Daemon_Timer(u_long data); ++int Daemon_getpwuid( uid_t uid, int unamelen, char *uname ); ++int Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg); ++void Init_Daemon_Queue( void ); ++int Queue_Daemon_Command(void *request, u_long reqlen, void *data, int dlen, void **reply, u_long *replen, int interruptible); ++void Queue_get(daemon_command_t *que); ++void Queue_put(daemon_command_t *que); ++void Uninit_Daemon_Queue( void ); ++int do_login(NclString *Server, NclString *Username, NclString *Password, u_long *lgnId, session_t Session); ++int do_logout( struct qstr *Server, session_t Session ); ++daemon_command_t *find_queue(u_long sequence); ++daemon_command_t *get_next_queue(int Set_Queue_Waiting); ++int NwdConvertNetwareHandle(PXPLAT pdata, daemon_handle_t *DHandle); ++int NwdConvertLocalHandle(PXPLAT pdata, daemon_handle_t *DHandle); ++int NwdGetMountPath(PXPLAT pdata); ++int NwdSetMapDrive(PXPLAT pdata, session_t Session); ++int NwdUnMapDrive(PXPLAT pdata, session_t Session); ++void RemoveDriveMaps( void ); ++int local_unlink(const char *pathname); ++ ++/*===[ Global variables ]=================================================*/ ++daemon_queue_t Daemon_Queue; ++ ++static DECLARE_WAIT_QUEUE_HEAD(Read_waitqueue); ++ ++u_long Sequence = 0; ++atomic_t Daemon_Open_Count=ATOMIC_INIT(0); ++ ++u_long Daemon_Command_Timeout = TIMEOUT_VALUE; ++ ++DECLARE_MUTEX ( DriveMapLock ); ++LIST_HEAD( DriveMapList ); ++ ++int MaxIoSize=PAGE_SIZE; ++ ++/*===[ Code ]=============================================================*/ ++ ++/*++======================================================================*/ ++void Init_Daemon_Queue() ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ INIT_LIST_HEAD(&Daemon_Queue.list); ++ spin_lock_init(&Daemon_Queue.lock); ++ init_MUTEX_LOCKED(&Daemon_Queue.semaphore); ++} ++ ++/*++======================================================================*/ ++void Uninit_Daemon_Queue( void ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ /* Does nothing for now but we maybe should clear the queue. */ ++} ++ ++/*++======================================================================*/ ++void ++NO_TRACE ++Daemon_Timer(u_long data) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que = (daemon_command_t *)data; ++ ++ if ( QUEUE_ACKED != que->status ) ++ { ++ que->status = QUEUE_TIMEOUT; ++ } ++ up(&que->semaphore); ++} ++ ++/*++======================================================================*/ ++int Queue_Daemon_Command( ++ void *request, ++ u_long reqlen, ++ void *data, ++ int dlen, ++ void **reply, ++ u_long *replen, ++ int interruptible) ++/* ++ * ++ * Arguments: void *request - pointer to the request that is to be sent. Needs to be kernel memory. ++ * int reqlen - length of the request. ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ int retCode = 0; ++ uint64_t ts1, ts2; ++ ++ ts1 = get_nanosecond_time(); ++ ++ DbgPrint( "Queue_Daemon_Command: 0x%x %d\n", request, reqlen); ++ ++ if (atomic_read(&Daemon_Open_Count)) ++ { ++ ++ que = (daemon_command_t *)Novfs_Malloc(sizeof(*que), GFP_KERNEL); ++ ++ DbgPrint( "Queue_Daemon_Command: que=0x%x\n", que); ++ if (que) ++ { ++ atomic_set( &que->reference, 0 ); ++ que->status = QUEUE_SENDING; ++ que->flags = 0; ++ ++ init_MUTEX_LOCKED(&que->semaphore); ++ ++ DbgPrint( "Queue_Daemon_Command: semaphore inited que=0x%x\n", que); ++ ++ que->sequence = InterlockedIncrement(&Sequence); ++ ++ DbgPrint( "Queue_Daemon_Command: sequence=0x%x\n", que->sequence); ++ ++ ((PCOMMAND_REQUEST_HEADER)request)->SequenceNumber = que->sequence; ++ ++ /* ++ * Setup and start que timer ++ */ ++ init_timer(&que->timer); ++ que->timer.expires = jiffies + (HZ * Daemon_Command_Timeout); ++ que->timer.data = (u_long)que; ++ que->timer.function = Daemon_Timer; ++ add_timer(&que->timer); ++ ++ DbgPrint( "Queue_Daemon_Command: timer started que=0x%x\n", que); ++ ++ /* ++ * Setup request ++ */ ++ que->request = request; ++ que->reqlen = reqlen; ++ que->data = data; ++ que->datalen = dlen; ++ que->reply = NULL; ++ que->replen = 0; ++ ++ DbgPrint( "Queue_Daemon_Command: setting up que=0x%x\n", que); ++ ++ /* ++ * Added entry to queue. ++ */ ++ DbgPrint( "Queue_Daemon_Command: Daemon_Queue locked\n"); ++ ++ /* ++ * Check to see if interruptible and set flags. ++ */ ++ if (interruptible) ++ { ++ que->flags |= INTERRUPTIBLE; ++ } ++ ++ Queue_get( que ); ++ ++ spin_lock(&Daemon_Queue.lock); ++ list_add_tail(&que->list, &Daemon_Queue.list); ++ spin_unlock(&Daemon_Queue.lock); ++ ++ DbgPrint( "Queue_Daemon_Command: 0x%x added to Daemon_Queue\n", que); ++ /* ++ * Signal that there is data to be read ++ */ ++ up(&Daemon_Queue.semaphore); ++ ++ /* ++ * Give a change to the other processes. ++ */ ++ yield(); ++ ++ DbgPrint( "Queue_Daemon_Command: calling down 0x%x\n", CURRENT_TIME); ++ ++ /* ++ * Block waiting for reply or timeout ++ */ ++ down(&que->semaphore); ++ ++ DbgPrint( "Queue_Daemon_Command: after down 0x%x\n", CURRENT_TIME); ++ ++ if ( QUEUE_ACKED == que->status ) ++ { ++ que->status = QUEUE_WAITING; ++ mod_timer(&que->timer, jiffies + (HZ * 2 * Daemon_Command_Timeout)); ++ DbgPrint( "Queue_Daemon_Command: mod_timer 0x%x\n", CURRENT_TIME); ++ if (interruptible) ++ { ++ retCode = down_interruptible(&que->semaphore); ++ } ++ else ++ { ++ down(&que->semaphore); ++ } ++ DbgPrint( "Queue_Daemon_Command: after down2 0x%x\n", CURRENT_TIME); ++ } ++ ++ DbgPrint( "Queue_Daemon_Command: after down 0x%d 0x%x\n", retCode, CURRENT_TIME); ++ /* ++ * Delete timer ++ */ ++ del_timer(&que->timer); ++ ++ /* ++ * Check for timeout ++ */ ++ if ((QUEUE_TIMEOUT == que->status) && (NULL == que->reply) ) ++ { ++ DbgPrint( "Queue_Daemon_Command: Timeout\n"); ++ retCode = -ETIME; ++ } ++ *reply = que->reply; ++ *replen = que->replen; ++ ++ /* ++ * Remove item from queue ++ */ ++ Queue_put( que ); ++ ++ } ++ else /* Error case with no memory */ ++ { ++ retCode = -ENOMEM; ++ *reply = NULL; ++ *replen = 0; ++ } ++ } ++ else ++ { ++ retCode = -EIO; ++ *reply = NULL; ++ *replen = 0; ++ ++ } ++ ts2 = get_nanosecond_time(); ++ ts2 = ts2-ts1; ++ ++ DbgPrint( "Queue_Daemon_Command: %llu retCode=%d \n", ts2, retCode); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++void Queue_get(daemon_command_t *Que) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DbgPrint("Queue_get: que=0x%p %d\n", Que, atomic_read(&Que->reference)); ++ atomic_inc( &Que->reference ); ++} ++ ++/*++======================================================================*/ ++void Queue_put(daemon_command_t *Que) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ++ DbgPrint("Queue_put: que=0x%p %d\n", Que, atomic_read(&Que->reference)); ++ spin_lock(&Daemon_Queue.lock); ++ ++ if ( atomic_dec_and_test( &Que->reference )) ++ { ++ /* ++ * Remove item from queue ++ */ ++ list_del(&Que->list); ++ spin_unlock(&Daemon_Queue.lock); ++ ++ /* ++ * Free item memory ++ */ ++ Novfs_Free(Que); ++ } ++ else ++ { ++ spin_unlock(&Daemon_Queue.lock); ++ } ++} ++ ++/*++======================================================================*/ ++daemon_command_t *get_next_queue(int Set_Queue_Waiting) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ ++ DbgPrint( "get_next_queue: que=0x%p\n", Daemon_Queue.list.next); ++ ++ spin_lock(&Daemon_Queue.lock); ++ que = (daemon_command_t *)Daemon_Queue.list.next; ++ ++ while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next) && ( que->status != QUEUE_SENDING ) ) ++ { ++ que = (daemon_command_t *)que->list.next; ++ } ++ ++ if ((NULL == que) || (que == (daemon_command_t *)&Daemon_Queue.list) || (que->status != QUEUE_SENDING)) ++ { ++ que = NULL; ++ } ++ else if (Set_Queue_Waiting) ++ { ++ que->status = QUEUE_WAITING; ++ } ++ ++ if (que) ++ { ++ atomic_inc( &que->reference ); ++ } ++ ++ spin_unlock(&Daemon_Queue.lock); ++ ++ DbgPrint( "get_next_queue: return=0x%x\n", que); ++ return(que); ++} ++ ++/*++======================================================================*/ ++daemon_command_t *find_queue(u_long sequence) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ ++ DbgPrint( "find_queue: 0x%x\n", sequence); ++ ++ spin_lock(&Daemon_Queue.lock); ++ que = (daemon_command_t *)Daemon_Queue.list.next; ++ ++ ++ while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next) && (que->sequence != sequence)) ++ { ++ que = (daemon_command_t *)que->list.next; ++ } ++ ++ if ((NULL == que) || (que == (daemon_command_t *)&Daemon_Queue.list.next) || (que->sequence != sequence)) ++ { ++ que = NULL; ++ } ++ ++ if (que) ++ { ++ atomic_inc( &que->reference ); ++ } ++ ++ spin_unlock(&Daemon_Queue.lock); ++ ++ DbgPrint( "find_queue: return 0x%p\n", que); ++ return(que); ++} ++/*++======================================================================*/ ++int Daemon_Open_Control(struct inode *Inode, struct file *File) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DbgPrint("Daemon_Open_Control: pid=%d Count=%d\n", current->pid, atomic_read(&Daemon_Open_Count)); ++ atomic_inc(&Daemon_Open_Count); ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Daemon_Close_Control(struct inode *Inode, struct file *File) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ ++ DbgPrint("Daemon_Close_Control: pid=%d Count=%d\n", current->pid, atomic_read(&Daemon_Open_Count)); ++ ++ if (atomic_dec_and_test(&Daemon_Open_Count)) ++ { ++ /* ++ * Signal any pending que itmes. ++ */ ++ ++ spin_lock(&Daemon_Queue.lock); ++ que = (daemon_command_t *)Daemon_Queue.list.next; ++ ++ while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next) && (que->status != QUEUE_DONE)) ++ { ++ que->status = QUEUE_TIMEOUT; ++ up(&que->semaphore); ++ ++ que = (daemon_command_t *)que->list.next; ++ } ++ spin_unlock(&Daemon_Queue.lock); ++ ++ RemoveDriveMaps(); ++ ++ Scope_Cleanup(); ++ } ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++ssize_t ++Daemon_Send_Command(struct file *file, char *buf, size_t len, loff_t *off) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ size_t retValue = 0; ++ int Finished=0; ++ PDATA_LIST dlist; ++ int i, dcnt, bcnt, ccnt, error; ++ char *vadr; ++ u_long cpylen; ++ ++ DbgPrint( "Daemon_Send_Command: %u %lld\n", len, *off); ++ if (len > MaxIoSize) ++ { ++ MaxIoSize = len; ++ } ++ ++ while ( !Finished ) ++ { ++ que = get_next_queue(1); ++ DbgPrint( "Daemon_Send_Command: 0x%x\n", que); ++ if (que) ++ { ++ retValue = que->reqlen; ++ if (retValue > len) ++ { ++ retValue = len; ++ } ++ if (retValue > 0x80) ++ mydump(0x80, que->request); ++ else ++ mydump(retValue, que->request); ++ ++ cpylen = copy_to_user(buf, que->request, retValue); ++ if (que->datalen && (retValue < len)) ++ { ++ buf += retValue; ++ dlist = que->data; ++ dcnt = que->datalen; ++ for (i=0; irwflag ) ++ { ++ bcnt = dlist->len; ++ DbgPrint("Daemon_Send_Command%d: page=0x%x offset=0x%x len=%d\n", i, dlist->page, dlist->offset, dlist->len); ++ if ((bcnt + retValue) <= len) ++ { ++ void *km_adr=NULL; ++ ++ if (dlist->page) ++ { ++ km_adr = kmap(dlist->page); ++ vadr = km_adr; ++ vadr += (u_int)dlist->offset; ++ } ++ else ++ { ++ vadr = dlist->offset; ++ } ++ ++ ccnt = copy_to_user(buf, vadr, bcnt); ++ ++ if ( km_adr ) ++ { ++ kunmap(dlist->page); ++ } ++ ++ DbgPrint("Daemon_Send_Command: Copy %d from 0x%x to 0x%x.\n", bcnt, vadr, buf); ++ if (bcnt > 0x80) ++ mydump(0x80, vadr); ++ else ++ mydump(bcnt, vadr); ++ ++ retValue += bcnt; ++ buf += bcnt; ++ } ++ else ++ { ++ break; ++ } ++ } ++ } ++ } ++ Queue_put( que ); ++ break; ++ } ++ ++ if (O_NONBLOCK & file->f_flags) ++ { ++ retValue = -EAGAIN; ++ break; ++ } ++ else ++ { ++ if ((error = down_interruptible(&Daemon_Queue.semaphore))) ++ { ++ DbgPrint( "Daemon_Send_Command: after down_interruptible error...%d\n", error); ++ retValue = -EINTR; ++ break; ++ } ++ DbgPrint( "Daemon_Send_Command: after down_interruptible\n"); ++ } ++ } ++ ++ *off = *off; ++ ++ DbgPrint( "Daemon_Send_Command: return 0x%x\n", retValue); ++ ++ return(retValue); ++} ++ ++/*++======================================================================*/ ++ssize_t ++Daemon_Receive_Reply(struct file * file, char * buf, size_t nbytes, loff_t *ppos) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ size_t retValue = 0; ++ void *reply; ++ u_long sequence, cpylen; ++ ++ PDATA_LIST dlist; ++ char *vadr; ++ int i; ++ ++ DbgPrint( "Daemon_Receive_Reply: buf=0x%x nbytes=%d ppos=%llx\n", buf, nbytes, *ppos); ++ ++ /* ++ * Get sequence number from reply buffer ++ */ ++ ++ cpylen = copy_from_user(&sequence, buf, sizeof(sequence)); ++ ++ /* ++ * Find item based on sequence number ++ */ ++ que = find_queue(sequence); ++ ++ DbgPrint( "Daemon_Receive_Reply: 0x%x 0x%x %d\n", sequence, que, nbytes); ++ if (que) ++ { ++ do ++ { ++ retValue = nbytes; ++ /* ++ * Ack packet from novfsd. Remove timer and ++ * return ++ */ ++ if (nbytes == sizeof(sequence)) ++ { ++ que->status = QUEUE_ACKED; ++ break; ++ } ++ ++ /* ++ * Set status that packet is done. ++ */ ++ que->status = QUEUE_DONE; ++ ++ if ( NULL != (dlist = que->data) ) ++ { ++ int thiscopy, left=nbytes; ++ retValue = 0; ++ ++ ++ DbgPrint( "Daemon_Receive_Reply: dlist=0x%x count=%d\n", dlist, que->datalen); ++ for (i=0; (i < que->datalen) && (retValue < nbytes); i++, dlist++) ++ { ++ DbgPrint( "Daemon_Receive_Reply:\n" \ ++ " dlist[%d].page: 0x%x\n" \ ++ " dlist[%d].offset: 0x%x\n" \ ++ " dlist[%d].len: 0x%x\n" \ ++ " dlist[%d].rwflag: 0x%x\n", ++ i, dlist->page, ++ i, dlist->offset, ++ i, dlist->len, ++ i, dlist->rwflag); ++ ++ if (DLWRITE == dlist->rwflag) ++ { ++ void *km_adr=NULL; ++ ++ if (dlist->page) ++ { ++ km_adr = kmap(dlist->page); ++ vadr = km_adr; ++ vadr += (u_int)dlist->offset; ++ } ++ else ++ { ++ vadr = dlist->offset; ++ } ++ ++ thiscopy = dlist->len; ++ if (thiscopy > left) ++ { ++ thiscopy = left; ++ dlist->len = left; ++ } ++ cpylen = copy_from_user(vadr, buf, thiscopy); ++ ++ if ( km_adr ) ++ { ++ kunmap(dlist->page); ++ } ++ ++ left -= thiscopy; ++ retValue += thiscopy; ++ buf += thiscopy; ++ } ++ } ++ que->replen = retValue; ++ } ++ else ++ { ++ reply = Novfs_Malloc(nbytes, GFP_KERNEL); ++ DbgPrint( "Daemon_Receive_Reply: reply=0x%x\n", reply); ++ if (reply) ++ { ++ retValue = nbytes; ++ que->reply = reply; ++ que->replen = nbytes; ++ ++ retValue -= copy_from_user(reply, buf, retValue); ++ if (retValue > 0x80) ++ mydump(0x80, reply); ++ else ++ mydump(retValue, reply); ++ ++ ++ } ++ else ++ { ++ retValue = -ENOMEM; ++ } ++ } ++ } while (0); ++ up(&que->semaphore); ++ Queue_put( que ); ++ } ++ ++ DbgPrint( "Daemon_Receive_Reply: return 0x%x\n", retValue); ++ ++ return(retValue); ++} ++ ++/*++======================================================================*/ ++int do_login(NclString *Server, NclString *Username, NclString *Password, u_long *lgnId, session_t Session) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PLOGIN_USER_REQUEST cmd; ++ PLOGIN_USER_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen, datalen; ++ u_char *data; ++ ++ datalen = Server->len+Username->len+Password->len; ++ cmdlen = sizeof(*cmd) + datalen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ data = (u_char *)cmd + sizeof(*cmd); ++ cmd->Command.CommandType = VFS_COMMAND_LOGIN_USER; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ ++ cmd->srvNameType = Server->type; ++ cmd->serverLength = Server->len; ++ cmd->serverOffset = (u_long)(data-(u_char *)cmd); ++ memcpy(data, Server->buffer, Server->len); ++ data += Server->len; ++ ++ cmd->usrNameType = Username->type; ++ cmd->userNameLength = Username->len; ++ cmd->userNameOffset = (u_long)(data-(u_char *)cmd); ++ memcpy(data, Username->buffer, Username->len); ++ data += Username->len; ++ ++ cmd->pwdNameType = Password->type; ++ cmd->passwordLength = Password->len; ++ cmd->passwordOffset = (u_long)(data-(u_char *)cmd); ++ memcpy(data, Password->buffer, Password->len); ++ data += Password->len; ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = reply->Reply.ErrorCode; ++ } ++ else ++ { ++ retCode = 0; ++ if (lgnId) ++ { ++ *lgnId = reply->loginIdentity; ++ } ++ } ++ Novfs_Free(reply); ++ } ++ memset(cmd, 0, cmdlen); ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++ ++} ++ ++/*++======================================================================*/ ++int do_logout( struct qstr *Server, session_t Session ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PLOGOUT_REQUEST cmd; ++ PLOGOUT_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen; ++ ++ cmdlen = (int)(&((PLOGOUT_REQUEST)0)->Name) + Server->len; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_LOGOUT_USER; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ ++ cmd->Length = Server->len; ++ memcpy(cmd->Name, Server->name, Server->len); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++ ++} ++ ++/*++======================================================================*/ ++int Daemon_getpwuid( uid_t uid, int unamelen, char *uname ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ GETPWUID_REQUEST cmd; ++ PGETPWUID_REPLY reply; ++ u_long replylen=0; ++ int retCode; ++ ++ cmd.Command.CommandType = VFS_COMMAND_GETPWUD; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = 0; ++ cmd.uid = uid; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ else ++ { ++ retCode = 0; ++ memset(uname, 0, unamelen); ++ replylen = replylen - (int)(&((PGETPWUID_REPLY)0)->UserName); ++ if (replylen) ++ { ++ if (replylen > unamelen) ++ { ++ retCode = -EINVAL; ++ replylen = unamelen-1; ++ } ++ memcpy(uname, reply->UserName, replylen); ++ } ++ } ++ Novfs_Free(reply); ++ } ++ return( retCode ); ++ ++} ++ ++/*++======================================================================*/ ++int Daemon_getversion( char *Buf, int Length ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ GET_VERSION_REQUEST cmd; ++ PGET_VERSION_REPLY reply; ++ u_long replylen=0; ++ int retVal=0; ++ ++ cmd.Command.CommandType = VFS_COMMAND_GET_VERSION; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = 0; ++ ++ Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retVal = -EIO; ++ } ++ else ++ { ++ retVal = replylen - (int)(&((PGET_VERSION_REPLY)0)->Version); ++ if (retVal < Length) ++ { ++ memcpy(Buf, reply->Version, retVal); ++ Buf[retVal] = '\0'; ++ } ++ } ++ Novfs_Free(reply); ++ } ++ return( retVal ); ++ ++} ++ ++/*++======================================================================*/ ++int Daemon_Login(PLOGIN Login, session_t Session) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOMEM; ++ LOGIN lLogin; ++ NclString server; ++ NclString username; ++ NclString password; ++ ++ if ( !copy_from_user(&lLogin, Login, sizeof(lLogin))) ++ { ++ if ( (server.buffer = Novfs_Malloc(lLogin.Server.Length, GFP_KERNEL)) ) ++ { ++ server.len = lLogin.Server.Length; ++ server.type = NWC_STRING_TYPE_ASCII; ++ if ( !copy_from_user((void *)server.buffer, lLogin.Server.Data, server.len) ) ++ { ++ if ( (username.buffer = Novfs_Malloc(lLogin.UserName.Length, GFP_KERNEL)) ) ++ { ++ username.len = lLogin.UserName.Length; ++ username.type = NWC_STRING_TYPE_ASCII; ++ if ( !copy_from_user((void *)username.buffer, lLogin.UserName.Data, username.len) ) ++ { ++ if ( (password.buffer = Novfs_Malloc(lLogin.Password.Length, GFP_KERNEL)) ) ++ { ++ password.len = lLogin.Password.Length; ++ password.type = NWC_STRING_TYPE_ASCII; ++ if ( !copy_from_user((void *)password.buffer, lLogin.Password.Data, password.len) ) ++ { ++ retCode = do_login(&server, &username, &password, NULL, Session); ++ if ( !retCode ) ++ { ++ char *username; ++ username = Scope_Get_UserName( NULL ); ++ if (username) ++ { ++ Novfs_Add_to_Root( username ); ++ } ++ } ++ } ++ memset(password.buffer, 0, password.len); ++ Novfs_Free(password.buffer); ++ } ++ } ++ memset(username.buffer, 0, username.len); ++ Novfs_Free(username.buffer); ++ } ++ } ++ Novfs_Free(server.buffer); ++ } ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Daemon_Logout(PLOGOUT Logout, session_t Session) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ LOGOUT lLogout; ++ struct qstr server; ++ int retCode=0; ++ ++ if ( !copy_from_user(&lLogout, Logout, sizeof(lLogout))) ++ { ++ if ( (server.name = Novfs_Malloc(lLogout.Server.Length, GFP_KERNEL)) ) ++ { ++ server.len = lLogout.Server.Length; ++ if ( !copy_from_user((void *)server.name, lLogout.Server.Data, server.len) ) ++ { ++ retCode = do_logout( &server, Session ); ++ } ++ Novfs_Free(server.name); ++ } ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Daemon_CreateSessionId( uint64_t *SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ CREATE_CONTEXT_REQUEST cmd; ++ PCREATE_CONTEXT_REPLY reply; ++ u_long replylen=0; ++ int retCode=0; ++ ++ DbgPrint("Daemon_CreateSessionId: %d\n", current->pid); ++ ++ cmd.Command.CommandType = VFS_COMMAND_CREATE_CONTEXT; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = 0; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ if ( !reply->Reply.ErrorCode && replylen > sizeof(COMMAND_REPLY_HEADER)) ++ { ++ *SessionId = reply->SessionId; ++ retCode = 0; ++ } ++ else ++ { ++ *SessionId = 0; ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ DbgPrint("Daemon_CreateSessionId: SessionId=0x%llx\n", *SessionId); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Daemon_DestroySessionId( uint64_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DESTROY_CONTEXT_REQUEST cmd; ++ PDESTROY_CONTEXT_REPLY reply; ++ u_long replylen=0; ++ int retCode=0; ++ ++ DbgPrint("Daemon_DestroySessionId: 0x%llx\n", SessionId); ++ ++ cmd.Command.CommandType = VFS_COMMAND_DESTROY_CONTEXT; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ if ( !reply->Reply.ErrorCode ) ++ { ++ drive_map_t *dm; ++ struct list_head *list; ++ ++ retCode = 0; ++ ++ /* ++ * When destroying the session check to see if there are any ++ * mapped drives. If there are then remove them. ++ */ ++ down( &DriveMapLock ); ++ list_for_each( list, &DriveMapList ) ++ { ++ dm = list_entry( list, drive_map_t, list ); ++ if ( SessionId == dm->session) ++ { ++ local_unlink( dm->name ); ++ list = list->prev; ++ list_del( &dm->list ); ++ Novfs_Free( dm ); ++ } ++ ++ } ++ up( &DriveMapLock ); ++ ++ } ++ else ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Daemon_Get_UserSpace( uint64_t SessionId, uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ GET_USER_SPACE_REQUEST cmd; ++ PGET_USER_SPACE_REPLY reply; ++ u_long replylen=0; ++ int retCode=0; ++ ++ DbgPrint("Daemon_Get_UserSpace: 0x%llx\n", SessionId); ++ ++ cmd.Command.CommandType = VFS_COMMAND_GET_USER_SPACE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ if ( !reply->Reply.ErrorCode ) ++ { ++ ++ DbgPrint("TotalSpace: %llu\n", reply->TotalSpace); ++ DbgPrint("FreeSpace: %llu\n", reply->FreeSpace); ++ DbgPrint("TotalEnties: %llu\n", reply->TotalEnties); ++ DbgPrint("FreeEnties: %llu\n", reply->FreeEnties); ++ ++ if (TotalSize) *TotalSize = reply->TotalSpace; ++ if (Free) *Free = reply->FreeSpace; ++ if (TotalEnties) *TotalEnties = reply->TotalEnties; ++ if (FreeEnties) *FreeEnties = reply->FreeEnties; ++ retCode = 0; ++ } ++ else ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Daemon_SetMountPoint ( char *Path ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSET_MOUNT_PATH_REQUEST cmd; ++ PSET_MOUNT_PATH_REPLY reply; ++ u_long replylen, cmdlen; ++ int retCode = -ENOMEM; ++ ++ DbgPrint("Daemon_SetMountPoint: %s\n", Path); ++ ++ replylen = strlen(Path); ++ ++ cmdlen = sizeof(SET_MOUNT_PATH_REQUEST) + replylen; ++ ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if ( cmd ) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_SET_MOUNT_PATH; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = 0; ++ cmd->PathLength = replylen; ++ ++ strcpy(cmd->Path, Path); ++ ++ replylen = 0; ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ if ( !reply->Reply.ErrorCode ) ++ { ++ retCode = 0; ++ } ++ else ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Daemon_SendDebugCmd ( char *Command ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DEBUG_REQUEST cmd; ++ PDEBUG_REPLY reply; ++ DEBUG_REPLY lreply; ++ u_long replylen, cmdlen; ++ DATA_LIST dlist[2]; ++ ++ int retCode = -ENOMEM; ++ ++ DbgPrint("Daemon_SendDebugCmd: %s\n", Command); ++ ++ dlist[0].page = NULL; ++ dlist[0].offset = (char *)Command; ++ dlist[0].len = strlen(Command); ++ dlist[0].rwflag = DLREAD; ++ ++ dlist[1].page = NULL; ++ dlist[1].offset = (char *)&lreply; ++ dlist[1].len = sizeof(lreply); ++ dlist[1].rwflag = DLWRITE; ++ ++ cmdlen = (int)(&((PDEBUG_REQUEST)0)->dbgcmd); ++ ++ cmd.Command.CommandType = VFS_COMMAND_DBG; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = 0; ++ cmd.cmdlen = strlen(Command); ++ ++ replylen = 0; ++ ++ retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, 2, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ Novfs_Free(reply); ++ } ++ if (0 == retCode) ++ { ++ retCode = lreply.Reply.ErrorCode; ++ } ++ ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int ++NO_TRACE ++Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOSYS; ++ u_long cpylen; ++ ++ ++ switch (cmd) ++ { ++ case IOC_LOGIN: ++ { ++ retCode = Daemon_Login((PLOGIN)arg, Scope_Get_SessionId( NULL )); ++ break; ++ } ++ ++ case IOC_LOGOUT: ++ { ++ retCode = Daemon_Logout((PLOGOUT)arg, Scope_Get_SessionId( NULL )); ++ break; ++ } ++ case IOC_DEBUGPRINT: ++ { ++ struct Ioctl_Debug { ++ int length; ++ char *data; ++ } io; ++ char *buf; ++ io.length = 0; ++ cpylen = copy_from_user(&io, (char *)arg, sizeof(io)); ++ if (io.length) ++ { ++ buf = Novfs_Malloc(io.length+1, GFP_KERNEL); ++ if (buf) ++ { ++ buf[0] = 0; ++ cpylen = copy_from_user(buf, io.data, io.length); ++ buf[io.length] = '\0'; ++ DbgPrint("%s", buf); ++ Novfs_Free(buf); ++ retCode = 0; ++ } ++ } ++ break; ++ } ++ ++ case IOC_XPLAT: ++ { ++ XPLAT data; ++ ++ cpylen = copy_from_user(&data, (void *)arg, sizeof(data)); ++ retCode = ((data.xfunction & 0x0000FFFF) | 0xCC000000); ++ ++ switch(data.xfunction) ++ { ++ case NWC_GET_MOUNT_PATH: ++ DbgPrint("[Daemon_ioctl] Call NwdGetMountPath\n"); ++ retCode = NwdGetMountPath( &data ); ++ break; ++ } ++ ++ DbgPrint("[NOVFS XPLAT] status Code = %X\n", retCode); ++ break; ++ } ++ ++ } ++ return (retCode); ++} ++ ++/*++======================================================================*/ ++int Daemon_Added_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_char *FHandle, u_long Mode, u_long Size) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_resource_t *resource; ++ int retVal = NWE_OUT_OF_HEAP_SPACE; ++ ++ if (FHandle) ++ DbgPrint("Daemon_Added_Resource: DHandle=0x%p Type=%d CHandle=0x%x FHandle=0x%x Mode=0x%x Size=%d\n", DHandle, Type, CHandle, *(u_long *)&FHandle[2], Mode, Size); ++ else ++ DbgPrint("Daemon_Added_Resource: DHandle=0x%p Type=%d CHandle=0x%x\n", DHandle, Type, CHandle); ++ ++ resource = Novfs_Malloc(sizeof(daemon_resource_t), GFP_KERNEL); ++ if (resource) ++ { ++ resource->type = Type; ++ resource->connection = CHandle; ++ if (FHandle) ++ { ++ memcpy( resource->handle, FHandle, sizeof(resource->handle) ); ++ } ++ else ++ { ++ memset( resource->handle, 0, sizeof(resource->handle) ); ++ } ++ resource->mode = Mode; ++ resource->size = Size; ++ write_lock( &DHandle->lock ); ++ list_add( &resource->list, &DHandle->list ); ++ write_unlock( &DHandle->lock ); ++ DbgPrint("Daemon_Added_Resource: Adding resource=0x%p\n", resource); ++ retVal = 0; ++ } ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int Daemon_Remove_Resource(daemon_handle_t *DHandle, int Type, u_long CHandle, u_long FHandle) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_resource_t *resource; ++ struct list_head *l; ++ int retVal = -ENOMEM; ++ ++ DbgPrint("Daemon_Remove_Resource: DHandle=0x%p Type=%d CHandle=0x%x FHandle=0x%x\n", DHandle, Type, CHandle, FHandle); ++ ++ write_lock( &DHandle->lock ); ++ ++ list_for_each( l, &DHandle->list ) ++ { ++ resource = list_entry( l, daemon_resource_t, list ); ++ ++ if ( (Type == resource->type) && ++ (resource->connection == CHandle) ) ++ { ++ DbgPrint("Daemon_Remove_Resource: Found resource=0x%p\n", resource); ++ l = l->prev; ++ list_del( &resource->list ); ++ Novfs_Free( resource ); ++ break; ++ } ++ } ++ ++ write_unlock( &DHandle->lock ); ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int Daemon_Library_open(struct inode *inode, struct file *file) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = -ENOMEM; ++ daemon_handle_t *dh; ++ ++ DbgPrint("Daemon_Library_open: inode=0x%p file=0x%p\n", inode, file); ++ ++ if ((dh = Novfs_Malloc(sizeof(daemon_handle_t), GFP_KERNEL))) ++ { ++ file->private_data = dh; ++ INIT_LIST_HEAD( &dh->list); ++ rwlock_init( &dh->lock ); ++ dh->session = Scope_Get_SessionId( NULL ); ++ retVal = 0; ++ } ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int Daemon_Library_close(struct inode *inode, struct file *file) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_handle_t *dh; ++ daemon_resource_t *resource; ++ struct list_head *l; ++ ++ char commanddata[sizeof(XPLAT_CALL_REQUEST)+sizeof(NwdCCloseConn)]; ++ PXPLAT_CALL_REQUEST cmd; ++ PXPLAT_CALL_REPLY reply; ++ PNwdCCloseConn nwdClose; ++ u_long cmdlen, replylen; ++ ++ DbgPrint("Daemon_Library_close: inode=0x%p file=0x%p\n", inode, file); ++ if (file->private_data) ++ { ++ dh = (daemon_handle_t *)file->private_data; ++ ++ list_for_each( l, &dh->list ) ++ { ++ resource = list_entry( l, daemon_resource_t, list ); ++ ++ if (DH_TYPE_STREAM == resource->type) ++ { ++ Novfs_Close_Stream( resource->connection, resource->handle, dh->session ); ++ } ++ else if (DH_TYPE_CONNECTION == resource->type) ++ { ++ cmd = (PXPLAT_CALL_REQUEST)commanddata; ++ cmdlen = offsetof(XPLAT_CALL_REQUEST, data) + sizeof(NwdCCloseConn); ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = dh->session; ++ cmd->NwcCommand = NWC_CLOSE_CONN; ++ ++ cmd->dataLen = sizeof(NwdCCloseConn); ++ nwdClose = (PNwdCCloseConn)cmd->data; ++ nwdClose->ConnHandle = resource->connection; ++ ++ Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, 0); ++ if (reply) ++ { ++ Novfs_Free(reply); ++ } ++ } ++ l = l->prev; ++ list_del( &resource->list ); ++ Novfs_Free( resource ); ++ } ++ Novfs_Free(dh); ++ file->private_data = NULL; ++ } ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++ssize_t Daemon_Library_read(struct file *file, char *buf, size_t len, loff_t *off) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_handle_t *dh; ++ daemon_resource_t *resource; ++ ++ size_t thisread, totalread=0; ++ loff_t offset = *off; ++ ++ DbgPrint("Daemon_Library_read: file=0x%p len=%d off=%lld\n", file, len, *off); ++ ++ if (file->private_data) ++ { ++ dh = file->private_data; ++ read_lock( &dh->lock ); ++ if (&dh->list != dh->list.next) ++ { ++ resource = list_entry( dh->list.next, daemon_resource_t, list ); ++ ++ if (DH_TYPE_STREAM == resource->type) ++ { ++ while( len > 0 && (offset < resource->size) ) ++ { ++ thisread = len; ++ if (Novfs_Read_Stream(resource->connection, ++ resource->handle, ++ buf, &thisread, ++ &offset, 1, ++ dh->session) || !thisread) ++ { ++ break; ++ } ++ len -= thisread; ++ buf += thisread; ++ offset += thisread; ++ totalread += thisread; ++ } ++ } ++ } ++ read_unlock( &dh->lock ); ++ } ++ *off = offset; ++ DbgPrint("Daemon_Library_read return = 0x%x\n", totalread); ++ return(totalread); ++} ++ ++/*++======================================================================*/ ++ssize_t Daemon_Library_write(struct file *file, const char *buf, size_t len, loff_t *off) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_handle_t *dh; ++ daemon_resource_t *resource; ++ ++ size_t thiswrite, totalwrite=-EINVAL; ++ loff_t offset = *off; ++ int status; ++ ++ DbgPrint("Daemon_Library_write: file=0x%p len=%d off=%lld\n", file, len, *off); ++ ++ if (file->private_data) ++ { ++ dh = file->private_data; ++ write_lock( &dh->lock ); ++ if (&dh->list != dh->list.next) ++ { ++ resource = list_entry( dh->list.next, daemon_resource_t, list ); ++ ++ if ( (DH_TYPE_STREAM == resource->type) && (len >= 0) ) ++ { ++ totalwrite = 0; ++ do ++ { ++ thiswrite = len; ++ status = Novfs_Write_Stream(resource->connection, ++ resource->handle, ++ (PVOID)buf, ++ &thiswrite, ++ &offset, ++ dh->session); ++ if ( status || !thiswrite ) ++ { ++ /* ++ * If len is zero then the file will have just been ++ * truncated to offset. Update size. ++ */ ++ if ( !status && !len ) ++ { ++ resource->size = offset; ++ } ++ totalwrite = status; ++ break; ++ } ++ len -= thiswrite; ++ buf += thiswrite; ++ offset += thiswrite; ++ totalwrite += thiswrite; ++ if (offset > resource->size) ++ { ++ resource->size = offset; ++ } ++ } while(len > 0); ++ } ++ } ++ write_unlock( &dh->lock ); ++ } ++ *off = offset; ++ DbgPrint("Daemon_Library_write return = 0x%x\n", totalwrite); ++ ++ return(totalwrite); ++} ++ ++/*++======================================================================*/ ++loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_handle_t *dh; ++ daemon_resource_t *resource; ++ ++ loff_t retVal = -EINVAL; ++ ++ DbgPrint("Daemon_Library_llseek: file=0x%p offset=%lld origin=%d\n", file, offset, origin); ++ ++ if (file->private_data) ++ { ++ dh = file->private_data; ++ read_lock( &dh->lock ); ++ if (&dh->list != dh->list.next) ++ { ++ resource = list_entry( dh->list.next, daemon_resource_t, list ); ++ ++ if (DH_TYPE_STREAM == resource->type) ++ { ++ switch (origin) { ++ case 2: ++ offset += resource->size; ++ break; ++ case 1: ++ offset += file->f_pos; ++ } ++ if (offset >= 0) { ++ if (offset != file->f_pos) { ++ file->f_pos = offset; ++ file->f_version = 0; ++ } ++ retVal = offset; ++ } ++ } ++ } ++ read_unlock( &dh->lock ); ++ } ++ ++ DbgPrint("Daemon_Library_llseek: ret %lld\n", retVal); ++ ++ return retVal; ++} ++ ++/*++======================================================================*/ ++int ++NO_TRACE ++Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u_long arg) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOSYS; ++ daemon_handle_t *dh; ++ u_long handle=0, cpylen; ++ ++ ++ dh = file->private_data; ++ ++ DbgPrint("Daemon_Library_ioctl: file=0x%p 0x%x 0x%x dh=0x%p\n", file, cmd, arg, dh); ++ ++ if (dh) ++ { ++ ++ switch (cmd) ++ { ++ case IOC_LOGIN: ++ { ++ retCode = Daemon_Login((PLOGIN)arg, dh->session); ++ break; ++ } ++ ++ case IOC_LOGOUT: ++ { ++ retCode = Daemon_Logout((PLOGOUT)arg, dh->session); ++ break; ++ } ++ ++ case IOC_DEBUGPRINT: ++ { ++ struct Ioctl_Debug { ++ int length; ++ char *data; ++ } io; ++ char *buf; ++ io.length = 0; ++ cpylen = copy_from_user(&io, (char *)arg, sizeof(io)); ++ if (io.length) ++ { ++ buf = Novfs_Malloc(io.length+1, GFP_KERNEL); ++ if (buf) ++ { ++ buf[0] = 0; ++ cpylen = copy_from_user(buf, io.data, io.length); ++ buf[io.length] = '\0'; ++ DbgPrint("%s", buf); ++ Novfs_Free(buf); ++ retCode = 0; ++ } ++ } ++ break; ++ } ++ ++ case IOC_XPLAT: ++ { ++ XPLAT data; ++ ++ cpylen = copy_from_user(&data, (void *)arg, sizeof(data)); ++ retCode = ((data.xfunction & 0x0000FFFF) | 0xCC000000); ++ ++ switch(data.xfunction) ++ { ++ case NWC_OPEN_CONN_BY_NAME: ++ DbgPrint("[VFS XPLAT] Call NwOpenConnByName\n"); ++ retCode = NwOpenConnByName(&data, &handle, dh->session); ++ if ( !retCode ) ++ { ++ Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, 0, 0, 0); ++ } ++ break; ++ ++ case NWC_OPEN_CONN_BY_ADDRESS: ++ DbgPrint("[VFS XPLAT] Call NwOpenConnByAddress\n"); ++ retCode = NwOpenConnByAddr(&data, &handle, dh->session); ++ if ( !retCode ) ++ { ++ Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, 0, 0, 0); ++ } ++ break; ++ ++ case NWC_OPEN_CONN_BY_REFERENCE: ++ ++ DbgPrint("[VFS XPLAT] Call NwOpenConnByReference\n"); ++ retCode = NwOpenConnByRef(&data, &handle, dh->session); ++ if ( !retCode ) ++ { ++ Daemon_Added_Resource(dh, DH_TYPE_CONNECTION, handle, 0, 0, 0); ++ } ++ break; ++ ++ case NWC_SYS_CLOSE_CONN: ++ DbgPrint("[VFS XPLAT] Call NwSysCloseConn\n"); ++ retCode = NwSysConnClose(&data, &handle, dh->session); ++ Daemon_Remove_Resource(dh, DH_TYPE_CONNECTION, handle, 0); ++ break; ++ ++ case NWC_CLOSE_CONN: ++ DbgPrint("[VFS XPLAT] Call NwCloseConn\n"); ++ retCode = NwConnClose(&data, &handle, dh->session); ++ Daemon_Remove_Resource(dh, DH_TYPE_CONNECTION, handle, 0); ++ break; ++ ++ case NWC_LOGIN_IDENTITY: ++ DbgPrint("[VFS XPLAT] Call NwLoginIdentity\n"); ++ retCode = NwLoginIdentity(&data, dh->session); ++ break; ++ ++ case NWC_RAW_NCP_REQUEST: ++ DbgPrint("[VFS XPLAT] Send Raw NCP Request\n"); ++ retCode = NwRawSend(&data, dh->session); ++ break; ++ ++ case NWC_AUTHENTICATE_CONN_WITH_ID: ++ DbgPrint("[VFS XPLAT] Authenticate Conn With ID\n"); ++ retCode = NwAuthConnWithId(&data, dh->session); ++ break; ++ ++ case NWC_UNAUTHENTICATE_CONN: ++ DbgPrint("[VFS XPLAT] UnAuthenticate Conn With ID\n"); ++ retCode = NwUnAuthenticate(&data, dh->session); ++ break; ++ ++ case NWC_LICENSE_CONN: ++ DbgPrint("Call NwLicenseConn\n"); ++ retCode = NwLicenseConn(&data, dh->session); ++ break; ++ ++ case NWC_LOGOUT_IDENTITY: ++ DbgPrint("[VFS XPLAT] Call NwLogoutIdentity\n"); ++ retCode = NwLogoutIdentity(&data, dh->session); ++ break; ++ ++ case NWC_UNLICENSE_CONN: ++ DbgPrint("[VFS XPLAT] Call NwUnlicense\n"); ++ retCode = NwUnlicenseConn(&data, dh->session); ++ break; ++ ++ case NWC_GET_CONN_INFO: ++ DbgPrint("[VFS XPLAT] Call NwGetConnInfo\n"); ++ retCode = NwGetConnInfo(&data, dh->session); ++ break; ++ ++ case NWC_SET_CONN_INFO: ++ DbgPrint("[VFS XPLAT] Call NwGetConnInfo\n"); ++ retCode = NwSetConnInfo(&data, dh->session); ++ break; ++ ++ case NWC_SCAN_CONN_INFO: ++ DbgPrint("[VFS XPLAT] Call NwScanConnInfo\n"); ++ retCode = NwScanConnInfo(&data, dh->session); ++ break; ++ ++ ++ case NWC_GET_IDENTITY_INFO: ++ DbgPrint("[VFS XPLAT] Call NwGetIdentityInfo\n"); ++ retCode = NwGetIdentityInfo(&data, dh->session); ++ break; ++ ++ case NWC_GET_REQUESTER_VERSION: ++ DbgPrint("[VFS XPLAT] Call NwGetDaemonVersion\n"); ++ retCode = NwGetDaemonVersion(&data, dh->session); ++ break; ++ ++ case NWC_GET_PREFERRED_DS_TREE: ++ DbgPrint("[VFS XPLAT] Call NwcGetPreferredDsTree\n"); ++ retCode = NwcGetPreferredDSTree(&data, dh->session); ++ break; ++ ++ case NWC_SET_PREFERRED_DS_TREE: ++ DbgPrint("[VFS XPLAT] Call NwcSetPreferredDsTree\n"); ++ retCode = NwcSetPreferredDSTree(&data, dh->session); ++ break; ++ ++ case NWC_GET_DEFAULT_NAME_CONTEXT: ++ DbgPrint("[VFS XPLAT] Call NwcGetDefaultNameContext\n"); ++ retCode = NwcGetDefaultNameCtx(&data, dh->session); ++ break; ++ ++ case NWC_SET_DEFAULT_NAME_CONTEXT: ++ DbgPrint("[VFS XPLAT] Call NwcSetDefaultNameContext\n"); ++ retCode = NwcSetDefaultNameCtx(&data, dh->session); ++ break; ++ ++ case NWC_QUERY_FEATURE: ++ DbgPrint("[VFS XPLAT] Call NwQueryFeature\n"); ++ retCode = NwQueryFeature(&data, dh->session); ++ break; ++ ++ ++ case NWC_GET_TREE_MONITORED_CONN_REF: ++ DbgPrint("[VFS XPLAT] Call NwcGetTreeMonitoredConn\n"); ++ retCode = NwcGetTreeMonitoredConn(&data, dh->session); ++ break; ++ ++ case NWC_ENUMERATE_IDENTITIES: ++ DbgPrint("[VFS XPLAT] Call NwcEnumerateIdentities\n"); ++ retCode = NwcEnumIdentities(&data, dh->session); ++ break; ++ ++ case NWC_CHANGE_KEY: ++ DbgPrint("[VFS XPLAT] Call NwcChangeAuthKey\n"); ++ retCode = NwcChangeAuthKey(&data, dh->session); ++ break; ++ ++ case NWC_CONVERT_LOCAL_HANDLE: ++ DbgPrint("[VFS XPLAT] Call NwdConvertLocalHandle\n"); ++ retCode = NwdConvertLocalHandle(&data, dh); ++ break; ++ ++ case NWC_CONVERT_NETWARE_HANDLE: ++ DbgPrint("[VFS XPLAT] Call NwdConvertNetwareHandle\n"); ++ retCode = NwdConvertNetwareHandle(&data, dh); ++ break; ++ ++ case NWC_SET_PRIMARY_CONN: ++ DbgPrint("[VFS XPLAT] Call NwcSetPrimaryConn\n"); ++ retCode = NwcSetPrimaryConn(&data, dh->session); ++ break; ++ ++ case NWC_GET_PRIMARY_CONN: ++ DbgPrint("[VFS XPLAT] Call NwcGetPrimaryConn\n"); ++ retCode = NwcGetPrimaryConn(&data, dh->session); ++ break; ++ ++ case NWC_MAP_DRIVE: ++ DbgPrint("[VFS XPLAT] Call NwcMapDrive\n"); ++ retCode = NwdSetMapDrive(&data, dh->session); ++ break; ++ ++ case NWC_UNMAP_DRIVE: ++ DbgPrint("[VFS XPLAT] Call NwcUnMapDrive\n"); ++ retCode = NwdUnMapDrive(&data, dh->session); ++ break; ++ ++ case NWC_ENUMERATE_DRIVES: ++ DbgPrint("[VFS XPLAT] Call NwcEnumerateDrives\n"); ++ retCode = NwcEnumerateDrives(&data, dh->session); ++ break; ++ ++ case NWC_GET_MOUNT_PATH: ++ DbgPrint("[VFS XPLAT] Call NwdGetMountPath\n"); ++ retCode = NwdGetMountPath( &data ); ++ break; ++ ++ case NWC_GET_BROADCAST_MESSAGE: ++ DbgPrint("[VSF XPLAT Call NwdGetBroadcastMessage\n"); ++ retCode = NwcGetBroadcastMessage(&data, dh->session); ++ break; ++ ++ case NWC_SET_KEY: ++ DbgPrint("[VSF XPLAT Call NwdSetKey\n"); ++ retCode = NwdSetKeyValue(&data, dh->session); ++ break; ++ ++ case NWC_VERIFY_KEY: ++ DbgPrint("[VSF XPLAT Call NwdVerifyKey\n"); ++ retCode = NwdVerifyKeyValue(&data, dh->session); ++ break; ++ ++ case NWC_RAW_NCP_REQUEST_ALL: ++ case NWC_NDS_RESOLVE_NAME_TO_ID: ++ case NWC_FRAGMENT_REQUEST: ++ case NWC_GET_CONFIGURED_NSPS: ++ default: ++ break; ++ ++ } ++ ++ DbgPrint("[NOVFS XPLAT] status Code = %X\n", retCode); ++ break; ++ } ++ } ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++unsigned int Daemon_Poll(struct file *file, struct poll_table_struct *poll_table) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ daemon_command_t *que; ++ unsigned int mask = POLLOUT | POLLWRNORM; ++ ++ que = get_next_queue(0); ++ if (que) ++ { ++ mask |= (POLLIN | POLLRDNORM); ++ } ++ else ++ { ++ ++ } ++ return(mask); ++} ++ ++ ++void Daemon_Dumpque( void ) ++{ ++#ifdef CONFIG_KDB ++ daemon_command_t *que; ++ ++ que = (daemon_command_t *)Daemon_Queue.list.next; ++ ++ while (que && (que != (daemon_command_t *)&Daemon_Queue.list.next)) ++ { ++ kdb_printf("DaemonQue:\n" \ ++ " Que: 0x%p\n" \ ++ " status: 0x%lx\n" \ ++ " flags: 0x%lx\n" \ ++ " semaphore: 0x%x\n" \ ++ " sequence: 0x%lx\n" \ ++ " timer: 0x%lx\n" \ ++ " request: 0x%p\n" \ ++ " reqlen: %ld\n" \ ++ " data: 0x%p\n" \ ++ " datalen: %d\n" \ ++ " reply: 0x%p\n" \ ++ " replen: %ld\n", ++ que, ++ que->status, ++ que->flags, ++ atomic_read(&que->semaphore.count), ++ que->sequence, ++ que->timer.expires, ++ que->request, ++ que->reqlen, ++ que->data, ++ que->datalen, ++ que->reply, ++ que->replen); ++ que = (daemon_command_t *)que->list.next; ++ } ++#endif ++} ++ ++/*++======================================================================*/ ++int NwdConvertNetwareHandle(PXPLAT pdata, daemon_handle_t *DHandle) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal; ++ NwcConvertNetWareHandle nh; ++ u_long cpylen; ++ ++ DbgPrint("NwdConvertNetwareHandle: DHandle=0x%p\n", DHandle); ++ ++ cpylen = copy_from_user(&nh, pdata->reqData, sizeof(NwcConvertNetWareHandle)); ++ ++ retVal = Daemon_Added_Resource(DHandle, DH_TYPE_STREAM, nh.ConnHandle, nh.NetWareHandle, nh.uAccessMode, nh.uFileSize); ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int NwdConvertLocalHandle(PXPLAT pdata, daemon_handle_t *DHandle) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = NWE_REQUESTER_FAILURE; ++ daemon_resource_t *resource; ++ NwcConvertLocalHandle lh; ++ struct list_head *l; ++ u_long cpylen; ++ ++ DbgPrint("NwdConvertLocalHandle: DHandle=0x%p\n", DHandle); ++ ++ read_lock( &DHandle->lock ); ++ ++ list_for_each( l, &DHandle->list ) ++ { ++ resource = list_entry( l, daemon_resource_t, list ); ++ ++ if ( DH_TYPE_STREAM == resource->type ) ++ { ++ lh.uConnReference = resource->connection; ++ ++ memcpy(lh.NwFileHandle, resource->handle, sizeof(resource->handle)); ++ if (pdata->repLen >= sizeof(NwcConvertLocalHandle)) ++ { ++ cpylen = copy_to_user(pdata->repData, &lh, sizeof(NwcConvertLocalHandle)); ++ retVal = 0; ++ } ++ else ++ { ++ retVal = NWE_BUFFER_OVERFLOW; ++ } ++ break; ++ } ++ } ++ ++ read_unlock( &DHandle->lock ); ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int NwdGetMountPath(PXPLAT pdata) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = NWE_REQUESTER_FAILURE; ++ int len; ++ u_long cpylen; ++ NwcGetMountPath mp; ++ ++ cpylen = copy_from_user(&mp, pdata->reqData, pdata->reqLen); ++ ++ if ( Novfs_CurrentMount ) ++ { ++ ++ len = strlen(Novfs_CurrentMount)+1; ++ if ( (len > mp.MountPathLen) && mp.pMountPath) ++ { ++ retVal = NWE_BUFFER_OVERFLOW; ++ } ++ else ++ { ++ if (mp.pMountPath) ++ { ++ cpylen = copy_to_user(mp.pMountPath, Novfs_CurrentMount, len); ++ } ++ retVal = 0; ++ } ++ ++ mp.MountPathLen = len; ++ ++ if (pdata->repData && (pdata->repLen >= sizeof(mp)) ) ++ { ++ cpylen = copy_to_user(pdata->repData, &mp, sizeof(mp)); ++ } ++ } ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int NwdSetMapDrive(PXPLAT pdata, session_t Session) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal; ++ u_long cpylen; ++ ++ retVal = NwcSetMapDrive(pdata, Session); ++ if ( !retVal ) ++ { ++ NwcMapDriveEx symInfo; ++ char *path; ++ drive_map_t *drivemap, *dm; ++ struct list_head *list; ++ ++ cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); ++ drivemap = Novfs_Malloc( sizeof(drive_map_t)+symInfo.linkOffsetLength, GFP_KERNEL ); ++ if (drivemap) ++ { ++ path = (char *)pdata->reqData; ++ path += symInfo.linkOffset; ++ cpylen = copy_from_user(drivemap->name, path, symInfo.linkOffsetLength); ++ ++ drivemap->session = Session; ++ drivemap->hash = full_name_hash(drivemap->name, symInfo.linkOffsetLength-1); ++ drivemap->namelen = symInfo.linkOffsetLength-1; ++ DbgPrint( "NwdSetMapDrive: hash=0x%x path=%s\n", drivemap->hash, drivemap->name); ++ ++ dm = (drive_map_t *)&DriveMapList.next; ++ ++ down( &DriveMapLock ); ++ ++ list_for_each( list, &DriveMapList ) ++ { ++ dm = list_entry( list, drive_map_t, list ); ++ DbgPrint( "NwdSetMapDrive: dm=0x%p\n" \ ++ " hash: 0x%x\n" \ ++ " namelen: %d\n" \ ++ " name: %s\n", ++ dm, dm->hash, dm->namelen, dm->name); ++ ++ if (drivemap->hash == dm->hash) ++ { ++ if ( 0 == strcmp(dm->name, drivemap->name)) ++ { ++ dm = NULL; ++ break; ++ } ++ } ++ else if (drivemap->hash < dm->hash) ++ { ++ break; ++ } ++ } ++ ++ if (dm) ++ { ++ if ( (dm == (drive_map_t *)&DriveMapList) || ++ (dm->hash < drivemap->hash) ) ++ { ++ list_add( &drivemap->list, &dm->list); ++ } ++ else ++ { ++ list_add_tail( &drivemap->list, &dm->list); ++ } ++ } ++ else ++ { ++ Novfs_Free( drivemap ); ++ } ++ up( &DriveMapLock ); ++ } ++ } ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int NwdUnMapDrive(PXPLAT pdata, session_t Session) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = NWE_REQUESTER_FAILURE; ++ u_long cpylen; ++ ++ retVal = NwcUnMapDrive(pdata, Session); ++ if ( !retVal ) ++ { ++ NwcUnmapDriveEx symInfo; ++ char *path; ++ drive_map_t *dm; ++ struct list_head *list; ++ u_long hash; ++ ++ ++ cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); ++ path = Novfs_Malloc( symInfo.linkLen, GFP_KERNEL ); ++ if (path) ++ { ++ cpylen = copy_from_user(path, ((NwcUnmapDriveEx *)pdata->reqData)->linkData, symInfo.linkLen); ++ ++ hash = full_name_hash(path, symInfo.linkLen-1); ++ DbgPrint( "NwdUnMapDrive: hash=0x%x path=%s\n", hash, path); ++ ++ dm = NULL; ++ ++ down( &DriveMapLock ); ++ ++ list_for_each( list, &DriveMapList ) ++ { ++ dm = list_entry( list, drive_map_t, list ); ++ DbgPrint( "NwdUnMapDrive: dm=0x%p %s\n" \ ++ " hash: 0x%x\n" \ ++ " namelen: %d\n", ++ dm, dm->name, dm->hash, dm->namelen); ++ ++ if (hash == dm->hash) ++ { ++ if ( 0 == strcmp(dm->name, path)) ++ { ++ break; ++ } ++ } ++ else if (hash < dm->hash) ++ { ++ dm = NULL; ++ break; ++ } ++ } ++ ++ if (dm) ++ { ++ DbgPrint( "NwdUnMapDrive: Remove dm=0x%p %s\n" \ ++ " hash: 0x%x\n" \ ++ " namelen: %d\n", ++ dm, dm->name, dm->hash, dm->namelen); ++ list_del( &dm->list ); ++ Novfs_Free( dm ); ++ } ++ ++ up( &DriveMapLock ); ++ } ++ } ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++void RemoveDriveMaps( void ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ drive_map_t *dm; ++ struct list_head *list; ++ ++ down( &DriveMapLock ); ++ list_for_each( list, &DriveMapList ) ++ { ++ dm = list_entry( list, drive_map_t, list ); ++ ++ DbgPrint( "RemoveDriveMap: dm=0x%p\n" \ ++ " hash: 0x%x\n" \ ++ " namelen: %d\n" \ ++ " name: %s\n", ++ dm, dm->hash, dm->namelen, dm->name); ++ local_unlink( dm->name ); ++ list = list->prev; ++ list_del( &dm->list ); ++ Novfs_Free( dm ); ++ } ++ up( &DriveMapLock ); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) ++/*++======================================================================*/ ++int local_unlink(const char *pathname) ++{ ++ int error; ++ struct dentry *dentry; ++ struct nameidata nd; ++ struct inode *inode = NULL; ++ ++ DbgPrint("local_unlink: %s\n", pathname); ++ error = path_lookup(pathname, LOOKUP_PARENT, &nd); ++ DbgPrint("local_unlink: path_lookup %d\n", error); ++ if ( !error ) ++ { ++ error = -EISDIR; ++ if (nd.last_type == LAST_NORM) ++ { ++ mutex_lock(&nd.dentry->d_inode->i_mutex); ++ dentry = lookup_create( &nd, 1); ++ DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry); ++ ++ error = PTR_ERR(dentry); ++ if (!IS_ERR(dentry)) ++ { ++ if (nd.last.name[nd.last.len]) ++ { ++ error = !dentry->d_inode ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; ++ } ++ else ++ { ++ inode = dentry->d_inode; ++ if (inode) ++ { ++ atomic_inc(&inode->i_count); ++ } ++ error = vfs_unlink(nd.dentry->d_inode, dentry); ++ DbgPrint("local_unlink: vfs_unlink %d\n", error); ++ } ++ dput(dentry); ++ } ++ mutex_unlock(&nd.dentry->d_inode->i_mutex); ++ ++ } ++ path_release(&nd); ++ } ++ ++ if (inode) ++ { ++ iput(inode); /* truncate the inode here */ ++ } ++ ++ DbgPrint("local_unlink: error=%d\n", error); ++ return error; ++} ++ ++#else ++/*++======================================================================*/ ++int local_unlink(const char *pathname) ++{ ++ int error; ++ struct dentry *dentry; ++ struct nameidata nd; ++ struct inode *inode = NULL; ++ ++ DbgPrint("local_unlink: %s\n", pathname); ++ error = path_lookup(pathname, LOOKUP_PARENT, &nd); ++ DbgPrint("local_unlink: path_lookup %d\n", error); ++ if ( !error ) ++ { ++ error = -EISDIR; ++ if (nd.last_type == LAST_NORM) ++ { ++ down(&nd.dentry->d_inode->i_sem); ++ dentry = lookup_one_len(&nd.last, nd.dentry, sizeof(nd.last)); ++ DbgPrint("local_unlink: lookup_hash 0x%p\n", dentry); ++ ++ error = PTR_ERR(dentry); ++ if (!IS_ERR(dentry)) ++ { ++ if (nd.last.name[nd.last.len]) ++ { ++ error = !dentry->d_inode ? -ENOENT : S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; ++ } ++ else ++ { ++ inode = dentry->d_inode; ++ if (inode) ++ { ++ atomic_inc(&inode->i_count); ++ } ++ error = vfs_unlink(nd.dentry->d_inode, dentry); ++ DbgPrint("local_unlink: vfs_unlink %d\n", error); ++ } ++ dput(dentry); ++ } ++ up(&nd.dentry->d_inode->i_sem); ++ } ++ path_release(&nd); ++ } ++ ++ if (inode) ++ { ++ iput(inode); /* truncate the inode here */ ++ } ++ ++ DbgPrint("local_unlink: error=%d\n", error); ++ return error; ++} ++#endif +diff -uNr src.old/src/file.c src/src/file.c +--- src.old/src/file.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/file.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,2318 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: file.c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module contains functions for accessing ++ * files through the daemon. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*===[ Include files specific to this module ]============================*/ ++#include "commands.h" ++#include "nwerror.h" ++#include "vfs.h" ++ ++/*===[ External data ]====================================================*/ ++extern struct dentry_operations Novfs_dentry_operations; ++extern int MaxIoSize; ++ ++ ++/*===[ External prototypes ]==============================================*/ ++extern int DbgPrint( char *Fmt, ... ); ++extern void mydump(int size, void *dumpptr); ++extern int Queue_Daemon_Command(void *request, u_long reqlen, void *data, int dlen, void **reply, u_long *replen, int interruptible); ++extern struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t uid); ++ ++extern void *Scope_Lookup( void ); ++ ++/*===[ Manifest constants ]===============================================*/ ++ ++/*===[ Type definitions ]=================================================*/ ++ ++/*===[ Function prototypes ]==============================================*/ ++ ++int Novfs_verify_file( struct qstr *Path, session_t SessionId ); ++int Novfs_get_alltrees(struct dentry *parent); ++ssize_t Novfs_tree_read(struct file *file, char *buf, size_t len, loff_t *off); ++ ++int Novfs_Get_Connected_Server_List( u_char **ServerList, session_t SessionId ); ++int Novfs_Get_Server_Volume_List( struct qstr *Server, u_char **VolumeList, session_t SessionId ); ++int Novfs_Find_Name_In_List( struct qstr *Name, u_char *List ); ++int Novfs_Verify_Server_Name( struct qstr *Server, session_t SessionId ); ++int Novfs_Verify_Volume_Name( struct qstr *Server, struct qstr *Volume, session_t SessionId ); ++int Novfs_Get_File_Info( u_char *Path, PENTRY_INFO Info, session_t SessionId ); ++int Novfs_Get_Directory_List( u_char *Path, u_long *EnumHandle, PENTRY_INFO Info, session_t SessionId ); ++int Novfs_Get_Directory_ListEx( u_char *Path, u_long *EnumHandle, int *Count, PENTRY_INFO *Info, session_t SessionId ); ++int Novfs_Open_File( u_char *Path, int Flags, PENTRY_INFO Info, u_long *Handle, session_t SessionId ); ++int Novfs_Create( u_char *Path, int DirectoryFlag, session_t SessionId ); ++int Novfs_Close_File( u_long Handle, session_t SessionId ); ++int Novfs_Read_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); ++int Novfs_Read_Pages( u_long Handle, PDATA_LIST DList, int DList_Cnt, size_t *Bytes, loff_t *Offset, session_t SessionId); ++int Novfs_Write_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); ++int Novfs_Write_Pages( u_long Handle, PDATA_LIST DList, int DList_Cnt, size_t Bytes, loff_t Offset, session_t SessionId); ++int Novfs_Read_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId); ++int Novfs_Write_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); ++int Novfs_Close_Stream( u_long ConnHandle, u_char *Handle, session_t SessionId ); ++int Novfs_Delete( u_char *Path, int DirectoryFlag, session_t SessionId ); ++int Novfs_Truncate_File( u_char *Path, int PathLen, session_t SessionId ); ++int Novfs_Rename_File( int DirectoryFlag, u_char *OldName, int OldLen, u_char *NewName, int NewLen, session_t SessionId ); ++int Novfs_Set_Attr( u_char *Path, struct iattr *Attr, session_t SessionId ); ++int Novfs_Get_File_Cache_Flag( u_char *Path, session_t SessionId ); ++ ++/*===[ Global variables ]=================================================*/ ++static struct file_operations Novfs_tree_operations = { ++ read: Novfs_tree_read, ++}; ++ ++/* ++ * StripTrailingDots was added because some apps will ++ * try and create a file name with a trailing dot. NetWare ++ * doesn't like this and will return an error. ++ */ ++u_char StripTrailingDots=1; ++ ++/*===[ Code ]=============================================================*/ ++ ++/*++======================================================================*/ ++int Novfs_verify_file( struct qstr *Path, scope_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PVERIFY_FILE_REPLY reply=NULL; ++ u_long replylen=0; ++ PVERIFY_FILE_REQUEST cmd; ++ int cmdlen; ++ int retCode=0; ++ ++ cmdlen = (int)(&((PVERIFY_FILE_REQUEST)0)->path) + Path->len; ++ cmd = (PVERIFY_FILE_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ cmd->pathLen = Path->len; ++ memcpy(cmd->path, Path->name, Path->len); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ DbgPrint("Novfs_verify_file: reply\n"); ++ mydump(replylen, reply); ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -ENOENT; ++ } ++ else ++ { ++ retCode = 0; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_get_alltrees(struct dentry *parent) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ u_char *p; ++ PCOMMAND_REPLY_HEADER reply=NULL; ++ u_long replylen=0; ++ COMMAND_REQUEST_HEADER cmd; ++ int retCode; ++ struct dentry *entry; ++ struct qstr name; ++ struct inode *inode; ++ ++ cmd.CommandType = 0; ++ cmd.SequenceNumber = 0; ++ cmd.SessionId = 0x1234; ++ ++ DbgPrint( "Novfs_get_alltrees:\n"); ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ DbgPrint( "Novfs_get_alltrees: relpy=0x%x replylen=%d\n", reply, replylen); ++ if (reply) ++ { ++ mydump(replylen, reply); ++ if ( !reply->ErrorCode && (replylen > sizeof(COMMAND_REPLY_HEADER))) ++ { ++ p = (char *)reply+8; ++ while (*p) ++ { ++ DbgPrint( "Novfs_get_alltrees: %s\n",p); ++ name.len = strlen(p); ++ name.name = p; ++ name.hash = full_name_hash(name.name, name.len); ++ entry = d_lookup(parent, &name); ++ if ( NULL == entry ) ++ { ++ DbgPrint( "Novfs_get_alltrees: adding %s\n",p); ++ entry = d_alloc(parent, &name); ++ if (entry) ++ { ++ entry->d_op = &Novfs_dentry_operations; ++ inode = Novfs_get_inode(parent->d_sb, S_IFREG | 0400, 0, 0); ++ if (inode) ++ { ++ inode->i_fop = &Novfs_tree_operations; ++ d_add(entry, inode); ++ } ++ } ++ } ++ p += (name.len+1); ++ } ++ } ++ Novfs_Free(reply); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++ssize_t Novfs_tree_read(struct file *file, char *buf, size_t len, loff_t *off) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ if (file->f_pos != 0) ++ { ++ return(0); ++ } ++ if (copy_to_user(buf, "Tree\n", 5)) ++ { ++ return(0); ++ } ++ return(5); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_Connected_Server_List( u_char **ServerList, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ GET_CONNECTED_SERVER_LIST_REQUEST req; ++ PGET_CONNECTED_SERVER_LIST_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode=0; ++ ++ *ServerList = NULL; ++ ++ req.Command.CommandType = VFS_COMMAND_GET_CONNECTED_SERVER_LIST; ++ req.Command.SessionId = SessionId; ++ ++ retCode = Queue_Daemon_Command(&req, sizeof(req), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ DbgPrint("Novfs_Get_Connected_Server_List: reply\n"); ++ replylen -= sizeof(COMMAND_REPLY_HEADER); ++ if ( !reply->Reply.ErrorCode && replylen ) ++ { ++ memcpy(reply, reply->List, replylen); ++ *ServerList = (u_char *)reply; ++ retCode = 0; ++ } ++ else ++ { ++ Novfs_Free(reply); ++ retCode = -ENOENT; ++ } ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_Server_Volume_List( struct qstr *Server, u_char **VolumeList, scope_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PGET_SERVER_VOLUME_LIST_REQUEST req; ++ PGET_SERVER_VOLUME_LIST_REPLY reply=NULL; ++ u_long replylen=0, reqlen; ++ int retCode; ++ ++ *VolumeList = NULL; ++ reqlen = sizeof(GET_SERVER_VOLUME_LIST_REQUEST)+Server->len; ++ req = Novfs_Malloc(reqlen, GFP_KERNEL); ++ if (req) ++ { ++ req->Command.CommandType = VFS_COMMAND_GET_SERVER_VOLUME_LIST; ++ req->Length = Server->len; ++ memcpy(req->Name, Server->name, Server->len); ++ req->Command.SessionId = SessionId; ++ ++ retCode = Queue_Daemon_Command(req, reqlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if ( reply ) ++ { ++ DbgPrint("Novfs_Get_Server_Volume_List: reply\n"); ++ mydump(replylen, reply); ++ replylen -= sizeof(COMMAND_REPLY_HEADER); ++ ++ if ( !reply->Reply.ErrorCode && replylen ) ++ { ++ memcpy(reply, reply->List, replylen); ++ *VolumeList = (u_char *)reply; ++ retCode = 0; ++ } ++ else ++ { ++ Novfs_Free(reply); ++ retCode = -ENOENT; ++ } ++ } ++ Novfs_Free(req); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Find_Name_In_List( struct qstr *Name, u_char *List ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int len; ++ int retCode = 0; ++ ++ while (*List) ++ { ++ len = strlen(List); ++ if ((len == Name->len) && !strncmp(Name->name, List, len)) ++ { ++ retCode = 1; ++ break; ++ } ++ List += (len+1); ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Verify_Server_Name( struct qstr *Server, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ u_char *list; ++ int retCode = 0; ++ ++ DbgPrint("Novfs_Verify_Server_Name: %.*s\n", Server->len, Server->name); ++ ++ list = NULL; ++ Novfs_Get_Connected_Server_List( &list, SessionId ); ++ ++ if (list) ++ { ++ retCode = Novfs_Find_Name_In_List( Server, list ); ++ Novfs_Free(list); ++ } ++ DbgPrint("Novfs_Verify_Server_Name: %d\n", retCode); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Verify_Volume_Name( struct qstr *Server, struct qstr *Volume, session_t SessionId ) ++/* ++ * ++ * Arguments: Server - Server name. ++ * Volume - Volume name to check for. ++ * ++ * Returns: zero - not found. ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ u_char *list; ++ int retCode = 0; ++ u_char *name; ++ int namelen; ++ struct qstr path; ++ ++ list = NULL; ++ namelen = Server->len+Volume->len+2; ++ name = Novfs_Malloc(namelen, GFP_KERNEL); ++ ++ if (name) ++ { ++ name[0] = '\\'; ++ memcpy(&name[1], Server->name, Server->len); ++ name[1+Server->len] = '\\'; ++ memcpy(&name[2+Server->len], Volume->name, Volume->len); ++ path.len = namelen; ++ path.name = name; ++ ++ if (Novfs_verify_file(&path, SessionId)) ++ { ++ retCode = 0; ++ } ++ else ++ { ++ retCode = 1; ++ } ++ ++ Novfs_Free(name); ++ } ++ else ++ { ++ ++ Novfs_Get_Server_Volume_List( Server, &list, SessionId ); ++ ++ if (list) ++ { ++ retCode = Novfs_Find_Name_In_List( Volume, list ); ++ Novfs_Free(list); ++ } ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_File_Info( u_char *Path, PENTRY_INFO Info, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PVERIFY_FILE_REPLY reply=NULL; ++ u_long replylen=0; ++ PVERIFY_FILE_REQUEST cmd; ++ int cmdlen; ++ int retCode=-ENOENT; ++ int pathlen; ++ ++ DbgPrint("Novfs_Get_File_Info: Path = %s\n", Path); ++ ++ Info->mode = S_IFDIR | 0700; ++ Info->uid = current->uid; ++ Info->gid = current->gid; ++ Info->size = 0; ++ Info->atime = Info->mtime = Info->ctime = CURRENT_TIME; ++ ++ if (Path && *Path) ++ { ++ pathlen = strlen(Path); ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[pathlen-1]) pathlen--; ++ } ++ cmdlen = (int)(&((PVERIFY_FILE_REQUEST)0)->path) + pathlen; ++ cmd = (PVERIFY_FILE_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ cmd->pathLen = pathlen; ++ memcpy(cmd->path, Path, cmd->pathLen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ ++ if ( reply->Reply.ErrorCode ) ++ { ++ retCode = -ENOENT; ++ } ++ else ++ { ++ Info->type = 3; ++ Info->mode = S_IRWXU; ++ ++ if (reply->fileMode & NW_ATTRIBUTE_DIRECTORY) ++ { ++ Info->mode |= S_IFDIR; ++ } ++ else ++ { ++ Info->mode |= S_IFREG; ++ } ++ ++ if (reply->fileMode & NW_ATTRIBUTE_READ_ONLY) ++ { ++ Info->mode &= ~(S_IWUSR); ++ } ++ ++ Info->uid = current->euid; ++ Info->gid = current->egid; ++ Info->size = reply->fileSize; ++ Info->atime.tv_sec = reply->lastAccessTime; ++ Info->atime.tv_nsec = 0; ++ Info->mtime.tv_sec = reply->modifyTime; ++ Info->mtime.tv_nsec = 0; ++ Info->ctime.tv_sec = reply->createTime; ++ Info->ctime.tv_nsec = 0; ++ DbgPrint("Novfs_Get_File_Info: replylen=%d sizeof(VERIFY_FILE_REPLY)=%d\n", replylen, sizeof(VERIFY_FILE_REPLY)); ++ if (replylen > sizeof(VERIFY_FILE_REPLY)) ++ { ++ long *lp = &reply->fileMode; ++ lp++; ++ DbgPrint("Novfs_Get_File_Info: extra data 0x%x\n", *lp); ++ Info->mtime.tv_nsec = *lp; ++ } ++ retCode = 0; ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ } ++ ++ DbgPrint("Novfs_Get_File_Info: return 0x%x\n", retCode); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_File_Info2( u_char *Path, PENTRY_INFO Info, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PVERIFY_FILE_REPLY reply=NULL; ++ u_long replylen=0; ++ PVERIFY_FILE_REQUEST cmd; ++ int cmdlen; ++ struct qstr server = {0}, volume = {0}; ++ u_char *p; ++ int i; ++ int retCode=-ENOENT; ++ p = Path; ++ ++ DbgPrint("Novfs_Get_File_Info: Path = %s\n", Path); ++ ++ Info->mode = S_IFDIR | 0700; ++ Info->uid = current->uid; ++ Info->gid = current->gid; ++ Info->size = 0; ++ Info->atime = Info->mtime = Info->ctime = CURRENT_TIME; ++ ++ if ('\\' == *p) ++ { ++ p++; ++ } ++ server.name = p; ++ ++ for(i=0; *p && ('\\' != *p); i++, p++); ++ server.len = i; ++ if (*p) ++ { ++ if ('\\' == *p) ++ { ++ p++; ++ } ++ volume.name = p; ++ for(i=0; *p && ('\\' != *p); i++, p++); ++ if (i) ++ { ++ volume.len = i; ++ if (*p) ++ { ++ if ('\\' == *p) ++ { ++ p++; ++ } ++ if (*p) ++ { ++ cmdlen = (int)(&((PVERIFY_FILE_REQUEST)0)->path) + strlen(Path); ++ cmd = (PVERIFY_FILE_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_VERIFY_FILE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ cmd->pathLen = strlen(Path); ++ memcpy(cmd->path, Path, cmd->pathLen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ ++ if ( reply->Reply.ErrorCode ) ++ { ++ retCode = -ENOENT; ++ } ++ else ++ { ++ Info->type = 3; ++ Info->mode = S_IRWXU; ++ ++ if (reply->fileMode & NW_ATTRIBUTE_DIRECTORY) ++ { ++ Info->mode |= S_IFDIR; ++ } ++ else ++ { ++ Info->mode |= S_IFREG; ++ } ++ ++ if (reply->fileMode & NW_ATTRIBUTE_READ_ONLY) ++ { ++ Info->mode &= ~(S_IWUSR); ++ } ++ ++ Info->uid = current->euid; ++ Info->gid = current->egid; ++ Info->size = reply->fileSize; ++ Info->atime.tv_sec = reply->lastAccessTime; ++ Info->atime.tv_nsec = 0; ++ Info->mtime.tv_sec = reply->modifyTime; ++ Info->mtime.tv_nsec = 0; ++ Info->ctime.tv_sec = reply->createTime; ++ Info->ctime.tv_nsec = 0; ++ retCode = 0; ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ } ++ } ++ } ++ if (('\0' == *p) && volume.len) ++ { ++ if ( Novfs_Verify_Volume_Name( &server, &volume, SessionId ) ) ++ { ++ retCode = 0; ++ Info->type = 2; ++ } ++ } ++ } ++ if (server.len && !volume.len) ++ { ++ if ( Novfs_Verify_Server_Name( &server, SessionId ) ) ++ { ++ retCode = 0; ++ Info->type = 1; ++ } ++ } ++ DbgPrint("Novfs_Get_File_Info: return 0x%x\n", retCode); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int begin_directory_enumerate( u_char *Path, int PathLen, u_long *EnumHandle, session_t SessionId) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PBEGIN_ENUMERATE_DIRECTORY_REQUEST cmd; ++ PBEGIN_ENUMERATE_DIRECTORY_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode, cmdlen; ++ ++ *EnumHandle = 0; ++ ++ cmdlen = (int)(&((PBEGIN_ENUMERATE_DIRECTORY_REQUEST)0)->path) + PathLen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_START_ENUMERATE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ ++ cmd->pathLen = PathLen; ++ memcpy(cmd->path, Path, PathLen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++/* ++ * retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, 0); ++ */ ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ else ++ { ++ *EnumHandle = reply->enumerateHandle; ++ retCode = 0; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int end_directory_enumerate( u_long EnumHandle, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ END_ENUMERATE_DIRECTORY_REQUEST cmd; ++ PEND_ENUMERATE_DIRECTORY_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode; ++ ++ ++ cmd.Command.CommandType = VFS_COMMAND_END_ENUMERATE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.enumerateHandle = EnumHandle; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, 0); ++ if (reply) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int directory_enumerate( u_long *EnumHandle, PENTRY_INFO Info, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ENUMERATE_DIRECTORY_REQUEST cmd; ++ PENUMERATE_DIRECTORY_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode; ++ ++ ++ cmd.Command.CommandType = VFS_COMMAND_ENUMERATE_DIRECTORY; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.enumerateHandle = *EnumHandle; ++ cmd.pathLen = 0; ++ cmd.path[0] = '\0'; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ /* ++ * The VFS_COMMAND_ENUMERATE_DIRECTORY call can return an ++ * error but there could still be valid data. ++ */ ++ if ( !reply->Reply.ErrorCode || ++ ( (replylen > sizeof(COMMAND_REPLY_HEADER)) && ++ (reply->nameLen > 0)) ) ++ { ++ Info->type = 3; ++ Info->mode = S_IRWXU; ++ ++ if (reply->mode & NW_ATTRIBUTE_DIRECTORY) ++ { ++ Info->mode |= S_IFDIR; ++ Info->mode |= S_IXUSR; ++ } ++ else ++ { ++ Info->mode |= S_IFREG; ++ } ++ ++ if (reply->mode & NW_ATTRIBUTE_READ_ONLY) ++ { ++ Info->mode &= ~(S_IWUSR); ++ } ++ ++ if (reply->mode & NW_ATTRIBUTE_EXECUTE) ++ { ++ Info->mode |= S_IXUSR; ++ } ++ ++ Info->uid = current->uid; ++ Info->gid = current->gid; ++ Info->size = reply->size; ++ Info->atime.tv_sec = reply->lastAccessTime; ++ Info->atime.tv_nsec = 0; ++ Info->mtime.tv_sec = reply->modifyTime; ++ Info->mtime.tv_nsec = 0; ++ Info->ctime.tv_sec = reply->createTime; ++ Info->ctime.tv_nsec = 0; ++ Info->namelength = reply->nameLen; ++ memcpy(Info->name, reply->name, reply->nameLen); ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -1; /* Eof of data */ ++ } ++ *EnumHandle = reply->enumerateHandle; ++ } ++ else ++ { ++ retCode = -ENODATA; ++ } ++ Novfs_Free(reply); ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int directory_enumerate_ex( u_long *EnumHandle, session_t SessionId, int *Count, PENTRY_INFO *PInfo, int Interrupt) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ENUMERATE_DIRECTORY_EX_REQUEST cmd; ++ PENUMERATE_DIRECTORY_EX_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode=0; ++ PENTRY_INFO info; ++ PENUMERATE_DIRECTORY_EX_DATA data; ++ int isize; ++ ++ if (PInfo) ++ { ++ *PInfo = NULL; ++ } ++ *Count = 0; ++ ++ cmd.Command.CommandType = VFS_COMMAND_ENUMERATE_DIRECTORY_EX; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.enumerateHandle = *EnumHandle; ++ cmd.pathLen = 0; ++ cmd.path[0] = '\0'; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, Interrupt); ++ ++ if (reply) ++ { ++ retCode = 0; ++ /* ++ * The VFS_COMMAND_ENUMERATE_DIRECTORY call can return an ++ * error but there could still be valid data. ++ */ ++ ++ if ( !reply->Reply.ErrorCode || ++ ( (replylen > sizeof(COMMAND_REPLY_HEADER)) && ++ (reply->enumCount > 0)) ) ++ { ++ DbgPrint("directory_enumerate_ex: isize=%d\n", replylen); ++ data = (PENUMERATE_DIRECTORY_EX_DATA)((char *)reply + sizeof(ENUMERATE_DIRECTORY_EX_REPLY)); ++ isize = replylen - ++ sizeof(PENUMERATE_DIRECTORY_EX_REPLY) - ++ reply->enumCount * (int)(&((PENUMERATE_DIRECTORY_EX_DATA)0)->name); ++ isize += (reply->enumCount * (int)(&((PENTRY_INFO)0)->name)); ++ ++ if (PInfo) ++ { ++ *PInfo = info = Novfs_Malloc(isize, GFP_KERNEL); ++ if ( *PInfo ) ++ { ++ DbgPrint("directory_enumerate_ex1: data=0x%p info=0x%p\n", data, info); ++ *Count = reply->enumCount; ++ do ++ { ++ DbgPrint("directory_enumerate_ex2: data=0x%p length=%d\n", data); ++ ++ info->type = 3; ++ info->mode = S_IRWXU; ++ ++ if (data->mode & NW_ATTRIBUTE_DIRECTORY) ++ { ++ info->mode |= S_IFDIR; ++ info->mode |= S_IXUSR; ++ } ++ else ++ { ++ info->mode |= S_IFREG; ++ } ++ ++ if (data->mode & NW_ATTRIBUTE_READ_ONLY) ++ { ++ info->mode &= ~(S_IWUSR); ++ } ++ ++ if (data->mode & NW_ATTRIBUTE_EXECUTE) ++ { ++ info->mode |= S_IXUSR; ++ } ++ ++ info->uid = current->euid; ++ info->gid = current->egid; ++ info->size = data->size; ++ info->atime.tv_sec = data->lastAccessTime; ++ info->atime.tv_nsec = 0; ++ info->mtime.tv_sec = data->modifyTime; ++ info->mtime.tv_nsec = 0; ++ info->ctime.tv_sec = data->createTime; ++ info->ctime.tv_nsec = 0; ++ info->namelength = data->nameLen; ++ memcpy(info->name, data->name, data->nameLen); ++ data = (PENUMERATE_DIRECTORY_EX_DATA)&data->name[data->nameLen]; ++ replylen = (int)((char *)&info->name[info->namelength] - (char *)info); ++ DbgPrint("directory_enumerate_ex3: info=0x%p\n", info); ++ mydump(replylen, info); ++ ++ info = (PENTRY_INFO)&info->name[info->namelength]; ++ ++ } while (--reply->enumCount); ++ } ++ } ++ ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -1; /* Eof of data */ ++ } ++ *EnumHandle = reply->enumerateHandle; ++ } ++ else ++ { ++ retCode = -ENODATA; ++ } ++ Novfs_Free(reply); ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_Directory_List( u_char *Path, u_long *EnumHandle, PENTRY_INFO Info, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOENT; ++ ++ if ( -1 == *EnumHandle) ++ { ++ return( -ENODATA ); ++ } ++ ++ if ( 0 == *EnumHandle ) ++ { ++ retCode = begin_directory_enumerate(Path, strlen(Path), EnumHandle, SessionId); ++ } ++ ++ if ( *EnumHandle ) ++ { ++ retCode = directory_enumerate( EnumHandle, Info, SessionId ); ++ if (retCode) ++ { ++ end_directory_enumerate( *EnumHandle, SessionId ); ++ if ( -1 == retCode ) ++ { ++ retCode = 0; ++ *EnumHandle = -1; ++ } ++ } ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_Directory_ListEx( u_char *Path, u_long *EnumHandle, int *Count, PENTRY_INFO *Info, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOENT; ++ ++ if (Count) *Count = 0; ++ if (Info) *Info = NULL; ++ ++ if ( -1 == *EnumHandle) ++ { ++ return( -ENODATA ); ++ } ++ ++ if ( 0 == *EnumHandle ) ++ { ++ retCode = begin_directory_enumerate(Path, strlen(Path), EnumHandle, SessionId); ++ } ++ ++ if ( *EnumHandle ) ++ { ++ retCode = directory_enumerate_ex( EnumHandle, SessionId, Count, Info, INTERRUPTIBLE ); ++ if (retCode) ++ { ++ end_directory_enumerate( *EnumHandle, SessionId ); ++ if ( -1 == retCode ) ++ { ++ retCode = 0; ++ *EnumHandle = -1; ++ } ++ } ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_Open_File( u_char *Path, int Flags, PENTRY_INFO Info, u_long *Handle, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ POPEN_FILE_REQUEST cmd; ++ POPEN_FILE_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen, pathlen; ++ ++ pathlen = strlen(Path); ++ ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[pathlen-1]) pathlen--; ++ } ++ ++ *Handle = 0; ++ ++ cmdlen = (int)(&((POPEN_FILE_REQUEST)0)->path) + pathlen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_OPEN_FILE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ ++ cmd->access = 0; ++ ++ if ( !(Flags & O_WRONLY) || (Flags & O_RDWR)) ++ { ++ cmd->access |= NWD_ACCESS_READ; ++ } ++ ++ if ((Flags & O_WRONLY) || (Flags & O_RDWR)) ++ { ++ cmd->access |= NWD_ACCESS_WRITE; ++ } ++ ++ switch (Flags & (O_CREAT | O_EXCL | O_TRUNC)) ++ { ++ case O_CREAT: ++ cmd->disp = NWD_DISP_OPEN_ALWAYS; ++ break; ++ ++ case O_CREAT | O_EXCL: ++ cmd->disp = NWD_DISP_CREATE_NEW; ++ break; ++ ++ case O_TRUNC: ++ cmd->disp = NWD_DISP_CREATE_ALWAYS; ++ break; ++ ++ case O_CREAT | O_TRUNC: ++ cmd->disp = NWD_DISP_CREATE_ALWAYS; ++ break; ++ ++ case O_CREAT | O_EXCL | O_TRUNC: ++ cmd->disp = NWD_DISP_CREATE_NEW; ++ break; ++ ++ default: ++ cmd->disp = NWD_DISP_OPEN_EXISTING; ++ break; ++ } ++ ++ cmd->mode = NWD_SHARE_READ | NWD_SHARE_WRITE | NWD_SHARE_DELETE; ++ ++ cmd->pathLen = pathlen; ++ memcpy(cmd->path, Path, pathlen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ if( NWE_OBJECT_EXISTS == reply->Reply.ErrorCode) ++ { ++ retCode = -EEXIST; ++ } ++ else if( NWE_ACCESS_DENIED == reply->Reply.ErrorCode) ++ { ++ retCode = -EACCES; ++ } ++ else ++ { ++ retCode = -ENOENT; ++ } ++ } ++ else ++ { ++ *Handle = reply->handle; ++ retCode = 0; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Create( u_char *Path, int DirectoryFlag, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PCREATE_FILE_REQUEST cmd; ++ PCREATE_FILE_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen, pathlen; ++ ++ pathlen = strlen(Path); ++ ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[pathlen-1]) pathlen--; ++ } ++ ++ cmdlen = (int)(&((PCREATE_FILE_REQUEST)0)->path) + pathlen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_CREATE_FILE; ++ if (DirectoryFlag) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_CREATE_DIRECOTRY; ++ } ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ ++ cmd->pathlength = pathlen; ++ memcpy(cmd->path, Path, pathlen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Close_File( u_long Handle, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ CLOSE_FILE_REQUEST cmd; ++ PCLOSE_FILE_REPLY reply; ++ u_long replylen=0; ++ int retCode; ++ ++ cmd.Command.CommandType = VFS_COMMAND_CLOSE_FILE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.handle = Handle; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, 0); ++ if (reply) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ return( retCode ); ++} ++/*++======================================================================*/ ++int Novfs_Read_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ READ_FILE_REQUEST cmd; ++ PREAD_FILE_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode = 0; ++ size_t len; ++ ++ len = *Bytes; ++ *Bytes = 0; ++ ++ if ( ((int)(&((PREAD_FILE_REPLY)0)->data) + len) > MaxIoSize) ++ { ++ len = MaxIoSize - (int)(&((PREAD_FILE_REPLY)0)->data); ++ len = (len/PAGE_SIZE)*PAGE_SIZE; ++ } ++ ++ cmd.Command.CommandType = VFS_COMMAND_READ_FILE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.handle = Handle; ++ cmd.len = len; ++ cmd.offset = *Offset; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ DbgPrint("Novfs_Read_File: Queue_Daemon_Command 0x%x replylen=%d\n", retCode, replylen); ++ ++ if (!retCode) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ else ++ { ++ replylen -= (int)(&((PREAD_FILE_REPLY)0)->data); ++ if (replylen > 0) ++ { ++ replylen -= copy_to_user(Buffer, reply->data, replylen); ++ *Bytes = replylen; ++ } ++ } ++ } ++ ++ if ( reply ) ++ { ++ Novfs_Free(reply); ++ } ++ ++ DbgPrint("Novfs_Read_File *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Read_Pages( u_long Handle, PDATA_LIST DList, int DList_Cnt, size_t *Bytes, loff_t *Offset, session_t SessionId) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ READ_FILE_REQUEST cmd; ++ PREAD_FILE_REPLY reply=NULL; ++ READ_FILE_REPLY lreply; ++ u_long replylen=0; ++ int retCode = 0; ++ size_t len; ++ ++ len = *Bytes; ++ *Bytes = 0; ++ ++ DbgPrint("Novfs_Read_File_Pages: Handle=0x%x Dlst=0x%p Dlcnt=%d Bytes=%d Offset=%lld SessionId=0x%llx\n", ++ Handle, DList, DList_Cnt, len, *Offset, SessionId); ++ ++ cmd.Command.CommandType = VFS_COMMAND_READ_FILE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.handle = Handle; ++ cmd.len = len; ++ cmd.offset = *Offset; ++ ++ /* ++ * Dlst first entry is reserved for reply header. ++ */ ++ DList[0].page = NULL; ++ DList[0].offset = &lreply; ++ DList[0].len = (int)(&((PREAD_FILE_REPLY)0)->data); ++ DList[0].rwflag = DLWRITE; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), DList, DList_Cnt, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ DbgPrint("Novfs_Read_File_Pages: Queue_Daemon_Command 0x%x\n", retCode); ++ ++ if (!retCode) ++ { ++ if (reply) ++ { ++ memcpy(&lreply, reply, sizeof(lreply)); ++ } ++ ++ if (lreply.Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ *Bytes = replylen - (int)(&((PREAD_FILE_REPLY)0)->data); ++ } ++ ++ if ( reply ) ++ { ++ Novfs_Free(reply); ++ } ++ ++ DbgPrint("Novfs_Read_File: retCode=0x%x\n", retCode); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Write_File( u_long Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ WRITE_FILE_REQUEST cmd; ++ PWRITE_FILE_REPLY reply=NULL; ++ unsigned long replylen=0; ++ int retCode=0, cmdlen; ++ size_t len; ++ ++ unsigned long boff; ++ struct page **pages; ++ DATA_LIST *dlist; ++ int res=0, npage, i; ++ WRITE_FILE_REPLY lreply; ++ ++ ++ len = *Bytes; ++ cmdlen = (int)(&((PWRITE_FILE_REQUEST)0)->data); ++ ++ *Bytes = 0; ++ ++ memset(&lreply, 0, sizeof(lreply)); ++ ++ DbgPrint("Novfs_Write_File cmdlen=%ld len=%ld\n", cmdlen, len); ++ ++ if ( (cmdlen+len) > MaxIoSize) ++ { ++ len = MaxIoSize-cmdlen; ++ len = (len/PAGE_SIZE)*PAGE_SIZE; ++ } ++ cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ cmd.handle = Handle; ++ cmd.len = len; ++ cmd.offset = *Offset; ++ ++ DbgPrint("Novfs_Write_File cmdlen=%ld len=%ld\n", cmdlen, len); ++ ++ npage = (((unsigned long)Buffer & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT; ++ ++ dlist = Novfs_Malloc(sizeof(DATA_LIST)*(npage+1), GFP_KERNEL); ++ if (NULL == dlist) ++ { ++ return(-ENOMEM); ++ } ++ ++ pages = Novfs_Malloc(sizeof(struct page *)*npage, GFP_KERNEL); ++ ++ if (NULL == pages) ++ { ++ Novfs_Free(dlist); ++ return(-ENOMEM); ++ } ++ ++ down_read(¤t->mm->mmap_sem); ++ ++ res = get_user_pages( ++ current, ++ current->mm, ++ (unsigned long)Buffer, ++ npage, ++ 0, /* read type */ ++ 0, /* don't force */ ++ pages, ++ NULL); ++ ++ up_read(¤t->mm->mmap_sem); ++ ++ DbgPrint("Novfs_Write_File res=%d\n", res); ++ ++ if ( res > 0 ) ++ { ++ boff = (unsigned long)Buffer & ~PAGE_MASK; ++ ++ flush_dcache_page(pages[0]); ++ dlist[0].page = pages[0]; ++ dlist[0].offset = (char *)boff; ++ dlist[0].len = PAGE_SIZE - boff; ++ dlist[0].rwflag = DLREAD; ++ ++ if (dlist[0].len > len) ++ { ++ dlist[0].len = len; ++ } ++ ++ DbgPrint("Novfs_Write_File0: page=0x%x offset=0x%p len=%d\n", dlist[0].page, dlist[0].offset, dlist[0].len); ++ ++ boff = dlist[0].len; ++ ++ DbgPrint("Novfs_Write_File len=%d boff=%d\n", len, boff); ++ ++ for (i=1; (i < res) && (boff < len); i++) ++ { ++ flush_dcache_page(pages[i]); ++ ++ dlist[i].page = pages[i]; ++ dlist[i].offset = NULL; ++ dlist[i].len = len-boff; ++ if (dlist[i].len > PAGE_SIZE) ++ { ++ dlist[i].len = PAGE_SIZE; ++ } ++ dlist[i].rwflag = DLREAD; ++ ++ boff += dlist[i].len; ++ DbgPrint("Novfs_Write_File%d: page=0x%x offset=0x%p len=%d\n", i, dlist[i].page, dlist[i].offset, dlist[i].len); ++ } ++ ++ dlist[i].page = NULL; ++ dlist[i].offset = &lreply; ++ dlist[i].len = sizeof(lreply); ++ dlist[i].rwflag = DLWRITE; ++ res++; ++ ++ DbgPrint("Novfs_Write_File Buffer=0x%x boff=0x%x len=%d\n", Buffer, boff, len); ++ ++ retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, res, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ } ++ else ++ { ++ char *kdata; ++ ++ res = 0; ++ ++ kdata = Novfs_Malloc(len, GFP_KERNEL); ++ if (kdata) ++ { ++ len -= copy_from_user(kdata, Buffer, len); ++ dlist[0].page = NULL; ++ dlist[0].offset = kdata; ++ dlist[0].len = len; ++ dlist[0].rwflag = DLREAD; ++ ++ dlist[1].page = NULL; ++ dlist[1].offset = &lreply; ++ dlist[1].len = sizeof(lreply); ++ dlist[1].rwflag = DLWRITE; ++ ++ retCode = Queue_Daemon_Command(&cmd, cmdlen, dlist, 2, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ Novfs_Free(kdata); ++ } ++ } ++ ++ DbgPrint("Novfs_Write_File retCode=0x%x reply=0x%x\n", retCode, reply); ++ ++ if ( !retCode ) ++ { ++ switch (lreply.Reply.ErrorCode) ++ { ++ case 0: ++ *Bytes = (size_t)lreply.bytesWritten; ++ retCode = 0; ++ break; ++ ++ case NWE_INSUFFICIENT_SPACE: ++ retCode = -ENOSPC; ++ break; ++ ++ case NWE_ACCESS_DENIED: ++ retCode = -EACCES; ++ break; ++ ++ default: ++ retCode = -EIO; ++ break; ++ } ++ } ++ ++ if ( res ) ++ { ++ for (i=0; idata); ++ ++ if (len) ++ { ++ cmd.Command.CommandType = VFS_COMMAND_WRITE_FILE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.handle = Handle; ++ cmd.len = len; ++ cmd.offset = Offset; ++ ++ retCode = Queue_Daemon_Command(&cmd, cmdlen, DList, DList_Cnt, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (!retCode) ++ { ++ if (reply) ++ { ++ memcpy(&lreply, reply, sizeof(lreply)); ++ } ++ switch (lreply.Reply.ErrorCode) ++ { ++ case 0: ++ retCode = 0; ++ break; ++ ++ case NWE_INSUFFICIENT_SPACE: ++ retCode = -ENOSPC; ++ break; ++ ++ case NWE_ACCESS_DENIED: ++ retCode = -EACCES; ++ break; ++ ++ default: ++ retCode = -EIO; ++ break; ++ } ++ } ++ if ( reply ) ++ { ++ Novfs_Free(reply); ++ } ++ } ++ DbgPrint("Novfs_Write_Pages retCode=0x%x\n", retCode); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Read_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, int User, session_t SessionId) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ READ_STREAM_REQUEST cmd; ++ PREAD_STREAM_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode = 0; ++ size_t len; ++ ++ len = *Bytes; ++ *Bytes = 0; ++ ++ if ( ((int)(&((PREAD_FILE_REPLY)0)->data) + len) > MaxIoSize) ++ { ++ len = MaxIoSize - (int)(&((PREAD_FILE_REPLY)0)->data); ++ len = (len/PAGE_SIZE)*PAGE_SIZE; ++ } ++ ++ cmd.Command.CommandType = VFS_COMMAND_READ_STREAM; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.connection = ConnHandle; ++ memcpy( cmd.handle, Handle, sizeof(cmd.handle)); ++ cmd.len = len; ++ cmd.offset = *Offset; ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ DbgPrint("Novfs_Read_Stream: Queue_Daemon_Command 0x%x replylen=%d\n", retCode, replylen); ++ ++ if ( reply ) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ else ++ { ++ replylen -= (int)(&((PREAD_STREAM_REPLY)0)->data); ++ if (replylen > 0) ++ { ++ if (User) ++ { ++ replylen -= copy_to_user(Buffer, reply->data, replylen); ++ } ++ else ++ { ++ memcpy(Buffer, reply->data, replylen); ++ } ++ ++ *Bytes = replylen; ++ } ++ } ++ Novfs_Free(reply); ++ } ++ ++ DbgPrint("Novfs_Read_Stream *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Write_Stream( u_long ConnHandle, u_char *Handle, u_char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PWRITE_STREAM_REQUEST cmd; ++ PWRITE_STREAM_REPLY reply=NULL; ++ u_long replylen=0; ++ int retCode=0, cmdlen; ++ size_t len; ++ ++ len = *Bytes; ++ cmdlen = len+(int)(&((PWRITE_STREAM_REQUEST)0)->data); ++ *Bytes = 0; ++ ++ if (cmdlen > MaxIoSize) ++ { ++ cmdlen = MaxIoSize; ++ len = cmdlen - (int)(&((PWRITE_STREAM_REQUEST)0)->data); ++ } ++ ++ DbgPrint("Novfs_Write_Stream cmdlen=%d len=%d\n", cmdlen, len); ++ ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ if (Buffer && len) ++ { ++ len -= copy_from_user(cmd->data, Buffer, len); ++ } ++ ++ DbgPrint("Novfs_Write_Stream len=%d\n", len); ++ ++ cmd->Command.CommandType = VFS_COMMAND_WRITE_STREAM; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ ++ cmd->connection = ConnHandle; ++ memcpy(cmd->handle, Handle, sizeof(cmd->handle)); ++ cmd->len = len; ++ cmd->offset = *Offset; ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ switch (reply->Reply.ErrorCode) ++ { ++ case 0: ++ retCode = 0; ++ break; ++ ++ case NWE_INSUFFICIENT_SPACE: ++ retCode = -ENOSPC; ++ break; ++ ++ case NWE_ACCESS_DENIED: ++ retCode = -EACCES; ++ break; ++ ++ default: ++ retCode = -EIO; ++ break; ++ } ++ DbgPrint("Novfs_Write_Stream reply->bytesWritten=0x%lx\n", reply->bytesWritten); ++ *Bytes = reply->bytesWritten; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ DbgPrint("Novfs_Write_Stream *Bytes=0x%x retCode=0x%x\n", *Bytes, retCode); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Close_Stream( u_long ConnHandle, u_char *Handle, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ CLOSE_STREAM_REQUEST cmd; ++ PCLOSE_STREAM_REPLY reply; ++ u_long replylen=0; ++ int retCode; ++ ++ cmd.Command.CommandType = VFS_COMMAND_CLOSE_STREAM; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.connection = ConnHandle; ++ memcpy(cmd.handle, Handle, sizeof(cmd.handle)); ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, 0); ++ if (reply) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Delete( u_char *Path, int DirectoryFlag, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PDELETE_FILE_REQUEST cmd; ++ PDELETE_FILE_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen, pathlen; ++ ++ pathlen = strlen(Path); ++ ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[pathlen-1]) pathlen--; ++ } ++ ++ cmdlen = (int)(&((PDELETE_FILE_REQUEST)0)->path) + pathlen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_DELETE_FILE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ ++ cmd->isDirectory = DirectoryFlag; ++ cmd->pathlength = pathlen; ++ memcpy(cmd->path, Path, pathlen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ if ((reply->Reply.ErrorCode & 0xFFFF) == 0x0006) /* Access Denied Error */ ++ { ++ retCode = -EACCES; ++ } ++ else ++ { ++ retCode = -EIO; ++ } ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Truncate_File( u_char *Path, int PathLen, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PTRUNCATE_FILE_REQUEST cmd; ++ PTRUNCATE_FILE_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen; ++ ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[PathLen-1]) PathLen--; ++ } ++ cmdlen = (int)(&((PTRUNCATE_FILE_REQUEST)0)->path) + PathLen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_TRUNCATE_FILE; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ ++ cmd->pathLen = PathLen; ++ memcpy(cmd->path, Path, PathLen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Rename_File( int DirectoryFlag, u_char *OldName, int OldLen, u_char *NewName, int NewLen, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ RENAME_FILE_REQUEST cmd; ++ PRENAME_FILE_REPLY reply; ++ u_long replylen=0; ++ int retCode; ++ ++ DbgPrint("Novfs_Rename_File:\n" \ ++ " DirectoryFlag: %d\n" \ ++ " OldName: %.*s\n" \ ++ " NewName: %.*s\n" \ ++ " SessionId: 0x%llx\n", ++ DirectoryFlag, ++ OldLen, OldName, ++ NewLen, NewName, ++ SessionId ); ++ ++ cmd.Command.CommandType = VFS_COMMAND_RENAME_FILE; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = SessionId; ++ ++ cmd.directoryFlag = DirectoryFlag; ++ ++ if (StripTrailingDots) ++ { ++ if ('.' == OldName[OldLen-1]) OldLen--; ++ if ('.' == NewName[NewLen-1]) NewLen--; ++ } ++ ++ cmd.newnameLen = NewLen; ++ memcpy(cmd.newname, NewName, NewLen); ++ ++ cmd.oldnameLen = OldLen; ++ memcpy(cmd.oldname, OldName, OldLen); ++ ++ retCode = Queue_Daemon_Command(&cmd, sizeof(cmd), NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = 0; ++ if (reply->Reply.ErrorCode) ++ { ++ retCode = -ENOENT; ++ } ++ Novfs_Free(reply); ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Set_Attr( u_char *Path, struct iattr *Attr, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSET_FILE_INFO_REQUEST cmd; ++ PSET_FILE_INFO_REPLY reply; ++ u_long replylen=0; ++ int retCode, cmdlen, pathlen; ++ ++ pathlen = strlen(Path); ++ ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[pathlen-1]) pathlen--; ++ } ++ ++ cmdlen = (int)(&((PSET_FILE_INFO_REQUEST)0)->path) + pathlen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_SET_FILE_INFO; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ cmd->fileInfo.ia_valid = Attr->ia_valid; ++ cmd->fileInfo.ia_mode = Attr->ia_mode; ++ cmd->fileInfo.ia_uid = Attr->ia_uid; ++ cmd->fileInfo.ia_gid = Attr->ia_uid; ++ cmd->fileInfo.ia_size = Attr->ia_size; ++ cmd->fileInfo.ia_atime = Attr->ia_atime.tv_sec; ++ cmd->fileInfo.ia_mtime = Attr->ia_mtime.tv_sec;; ++ cmd->fileInfo.ia_ctime = Attr->ia_ctime.tv_sec;; ++/* ++ cmd->fileInfo.ia_attr_flags = Attr->ia_attr_flags; ++*/ ++ cmd->fileInfo.ia_attr_flags = 0; ++ ++ cmd->pathlength = pathlen; ++ memcpy(cmd->path, Path, pathlen); ++ ++ retCode = Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ switch( reply->Reply.ErrorCode ) ++ { ++ case 0: ++ retCode = 0; ++ break; ++ ++ case NWE_PARAM_INVALID: ++ retCode = -EINVAL; ++ break; ++ ++ default: ++ retCode = -EIO; ++ break; ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_Get_File_Cache_Flag( u_char *Path, session_t SessionId ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PGET_CACHE_FLAG_REQUEST cmd; ++ PGET_CACHE_FLAG_REPLY reply=NULL; ++ u_long replylen=0; ++ int cmdlen; ++ int retCode = 0; ++ int pathlen; ++ ++ DbgPrint("Novfs_Get_File_Cache_Flag: Path = %s\n", Path); ++ ++ if (Path && *Path) ++ { ++ pathlen = strlen(Path); ++ if (StripTrailingDots) ++ { ++ if ('.' == Path[pathlen-1]) pathlen--; ++ } ++ cmdlen = (int)(&((PGET_CACHE_FLAG_REQUEST)0)->path) + pathlen; ++ cmd = (PGET_CACHE_FLAG_REQUEST)Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_GET_CACHE_FLAG; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = SessionId; ++ cmd->pathLen = pathlen; ++ memcpy(cmd->path, Path, cmd->pathLen); ++ ++ Queue_Daemon_Command(cmd, cmdlen, NULL, 0, (void *)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ ++ if ( !reply->Reply.ErrorCode ) ++ { ++ retCode = reply->CacheFlag; ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ } ++ ++ DbgPrint("Novfs_Get_File_Cache_Flag: return %d\n", retCode); ++ return(retCode); ++} +diff -uNr src.old/src/inode.c src/src/inode.c +--- src.old/src/inode.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/inode.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,5236 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: inode.c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module contains functions used to control ++ * access to the Linux file system. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*===[ Include files specific to this module ]============================*/ ++#include "vfs.h" ++ ++/*===[ External data ]====================================================*/ ++extern int MaxIoSize; ++ ++/*===[ External prototypes ]==============================================*/ ++extern int DbgPrint( char *Fmt, ... ); ++extern int LocalPrint( char *Fmt, ... ); ++ ++extern int Init_Procfs_Interface( void ); ++extern void Uninit_Procfs_Interface( void ); ++extern void mydump(int size, void *dumpptr); ++ ++/* ++ * Daemon.c functions ++ */ ++extern void Init_Daemon_Queue( void ); ++extern void Uninit_Daemon_Queue( void ); ++extern int do_logout( struct qstr *Server ); ++extern int Daemon_SetMountPoint( char *Path ); ++ ++/* ++ * file.c functions ++ */ ++extern int Novfs_verify_file( struct qstr *Path, session_t SessionId ); ++extern int Novfs_get_alltrees(struct dentry *parent); ++extern int Novfs_Get_Connected_Server_List( unsigned char **ServerList, session_t SessionId ); ++extern int Novfs_Get_Server_Volume_List( struct qstr *Server, unsigned char **VolumeList, session_t SessionId ); ++extern int Novfs_Verify_Server_Name( struct qstr *Server, session_t SessionId ); ++extern int Novfs_Verify_Volume_Name( struct qstr *Server, struct qstr *Volume, session_t SessionId ); ++extern int Novfs_Get_File_Info( unsigned char *Path, PENTRY_INFO Info, session_t SessionId ); ++extern int Novfs_Get_Directory_List( unsigned char *Path, unsigned long *EnumHandle, PENTRY_INFO Info, session_t SessionId ); ++extern int Novfs_Get_Directory_ListEx( unsigned char *Path, unsigned long *EnumHandle, int *Count, PENTRY_INFO *Info, session_t SessionId ); ++extern int Novfs_Open_File( unsigned char *Path, int Flags, PENTRY_INFO Info, unsigned long *Handle, session_t SessionId ); ++extern int Novfs_Create( unsigned char *Path, int DirectoryFlag, session_t SessionId ); ++extern int Novfs_Close_File( unsigned long Handle, session_t SessionId ); ++extern int Novfs_Read_File( unsigned long Handle, unsigned char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); ++extern int Novfs_Read_Pages( u_long Handle, PDATA_LIST DList, int DList_Cnt, size_t *Bytes, loff_t *Offset, session_t SessionId); ++extern int Novfs_Write_File( unsigned long Handle, unsigned char *Buffer, size_t *Bytes, loff_t *Offset, session_t SessionId); ++extern int Novfs_Write_Pages( unsigned long Handle, PDATA_LIST DList, int DList_Cnt, size_t Bytes, loff_t Offset, session_t SessionId); ++extern int Novfs_Delete( unsigned char *Path, int DirectoryFlag, session_t SessionId ); ++extern int Novfs_Truncate_File( unsigned char *Path, int PathLen, session_t SessionId ); ++extern int Novfs_Rename_File( int DirectoryFlag, unsigned char *OldName, int OldLen, unsigned char *NewName, int NewLen, session_t SessionId ); ++extern int Novfs_Set_Attr( unsigned char *Path, struct iattr *Attr, session_t SessionId ); ++extern int Novfs_Get_File_Cache_Flag( u_char *Path, session_t SessionId ); ++ ++/* ++ * scope.c functions ++ */ ++extern void Scope_Init( void ); ++extern void Scope_Uninit( void ); ++extern void *Scope_Lookup( void ); ++extern unsigned long Scope_Get_Hash( void *); ++extern uid_t Scope_Get_Uid( void *); ++extern session_t Scope_Get_SessionId( void *Scope ); ++extern void *Scope_Get_ScopefromName( struct qstr *Name ); ++extern void *Scope_Get_ScopefromPath( struct dentry *Dentry ); ++extern char *Scope_Get_ScopeUsers( void ); ++extern int Scope_Set_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); ++extern int Scope_Get_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); ++extern char *Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags); ++ ++/* ++ * profile.c functions ++ */ ++extern int init_profile( void ); ++extern void uninit_profile( void ); ++ ++/*===[ Manifest constants ]===============================================*/ ++#define FILE_UPDATE_TIMEOUT 2 ++ ++/*===[ Type definitions ]=================================================*/ ++ ++/*===[ Function prototypes ]==============================================*/ ++int Novfs_Remove_from_Root(char *RemoveName); ++int Novfs_Add_to_Root(char *); ++char *Novfs_dget_path( struct dentry *d, char *path, unsigned int pathlen ); ++int verify_dentry(struct dentry *dentry, int Flags); ++int invalidate_dentry(struct dentry *parent); ++struct dentry *Novfs_d_lookup(struct dentry *Parent, struct qstr *Name); ++int Novfs_d_add(struct dentry *p, struct dentry *d, struct inode *i, int add); ++int Novfs_d_strcmp (struct qstr *s1, struct qstr *s2); ++struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t uid, ino_t ino, struct qstr *name); ++unsigned long Novfs_internal_hash (struct qstr *name); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ int Novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data, struct vfsmount *Mnt); ++#else ++ struct super_block * Novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data); ++#endif ++ ++void Novfs_kill_sb(struct super_block *SB); ++int Novfs_fill_super (struct super_block *SB, void *Data, int Silent); ++ ++/* ++ * Declared dentry_operations ++ */ ++int Novfs_d_revalidate(struct dentry *, struct nameidata *); ++int Novfs_d_hash (struct dentry *, struct qstr *); ++int Novfs_d_compare (struct dentry *, struct qstr *, struct qstr *); ++int Novfs_d_delete(struct dentry *dentry); ++void Novfs_d_release(struct dentry *dentry); ++void Novfs_d_iput(struct dentry *dentry, struct inode *inode); ++ ++/* ++ * Declared directory operations ++ */ ++int Novfs_dir_open(struct inode *inode, struct file *file); ++int Novfs_dir_release(struct inode *inode, struct file *file); ++loff_t Novfs_dir_lseek(struct file *file, loff_t offset, int origin); ++int Novfs_dir_read(struct file *file, char *buf, size_t len, loff_t *off); ++void addtodentry( struct dentry *Parent, unsigned char *List, int Level ); ++int Novfs_filldir(void *data, const char *name, int namelen, loff_t off, ino_t ino, unsigned ftype); ++int Novfs_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); ++int Novfs_dir_fsync(struct file * file, struct dentry *dentry, int datasync); ++ ++/* ++ * Declared address space operations ++ */ ++int Novfs_a_writepage(struct page* page, struct writeback_control *wbc); ++int Novfs_a_writepages(struct address_space *mapping, struct writeback_control *wbc); ++int Novfs_a_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to); ++int Novfs_a_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to); ++int Novfs_a_readpage(struct file *file, struct page *page); ++int Novfs_a_readpages(struct file *file, struct address_space *mapping, struct list_head *page_lst, unsigned nr_pages); ++ssize_t Novfs_a_direct_IO(int rw, struct kiocb *kiocb, ++ const struct iovec *iov, ++ loff_t offset, ++ unsigned long nr_segs); ++ ++/* ++ * Declared file_operations ++ */ ++ssize_t Novfs_f_read(struct file *, char *, size_t, loff_t *); ++ssize_t Novfs_f_write(struct file *, const char *, size_t, loff_t *); ++int Novfs_f_readdir(struct file *, void *, filldir_t); ++int Novfs_f_ioctl(struct inode *, struct file *, unsigned int, unsigned long); ++int Novfs_f_mmap(struct file * file, struct vm_area_struct * vma); ++int Novfs_f_open(struct inode *, struct file *); ++int Novfs_f_flush(struct file *); ++int Novfs_f_release(struct inode *, struct file *); ++int Novfs_f_fsync(struct file *, struct dentry *, int datasync); ++int Novfs_f_lock(struct file *, int, struct file_lock *); ++ ++/* ++ * Declared inode_operations ++ */ ++int Novfs_i_create(struct inode *,struct dentry *,int, struct nameidata *); ++struct dentry * Novfs_i_lookup(struct inode *,struct dentry *, struct nameidata *); ++int Novfs_i_mkdir(struct inode *,struct dentry *,int); ++int Novfs_i_unlink(struct inode *dir, struct dentry *dentry); ++int Novfs_i_rmdir(struct inode *,struct dentry *); ++int Novfs_i_mknod(struct inode *,struct dentry *,int,dev_t); ++int Novfs_i_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); ++int Novfs_i_permission(struct inode *inode, int mask); ++int Novfs_i_setattr(struct dentry *, struct iattr *); ++int Novfs_i_getattr(struct vfsmount *mnt, struct dentry *, struct kstat *); ++int Novfs_i_revalidate(struct dentry *dentry); ++ ++void update_inode(struct inode *Inode, PENTRY_INFO Info); ++ ++/* ++ * Declared super_operations ++ */ ++void Novfs_read_inode(struct inode *inode); ++void Novfs_write_inode(struct inode *inode); ++int Novfs_notify_change(struct dentry *dentry, struct iattr *attr); ++void Novfs_clear_inode(struct inode *inode); ++int Novfs_show_options( struct seq_file *s, struct vfsmount *m ); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ int Novfs_statfs(struct dentry *de, struct kstatfs *buf); ++#else ++ int Novfs_statfs(struct super_block *sb, struct kstatfs *buf); ++#endif ++ ++/* ++ * Declared control interface functions ++ */ ++ssize_t ++Novfs_Control_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos); ++ ++ssize_t ++Novfs_Control_write(struct file * file, const char * buf, size_t nbytes, loff_t *ppos); ++ ++int Novfs_Control_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++ ++int __init init_novfs(void); ++void __exit exit_novfs(void); ++ ++int Novfs_lock_inode_cache( struct inode *i ); ++void Novfs_unlock_inode_cache( struct inode *i ); ++int Novfs_enumerate_inode_cache( struct inode *i, struct list_head **iteration, ino_t *ino, PENTRY_INFO info); ++int Novfs_get_entry( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info); ++int Novfs_get_entry_by_pos( struct inode *i, loff_t pos, ino_t *ino, PENTRY_INFO info); ++int Novfs_get_entry_time( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info, u64 *EntryTime); ++int Novfs_get_remove_entry( struct inode *i, ino_t *ino, PENTRY_INFO info); ++void Novfs_invalidate_inode_cache( struct inode *i ); ++PDIR_CACHE Novfs_lookup_inode_cache( struct inode *i, struct qstr *name, ino_t ino ); ++int Novfs_lookup_validate( struct inode *i, struct qstr *name, ino_t ino ); ++int Novfs_add_inode_entry( struct inode *i, struct qstr *name, ino_t ino, PENTRY_INFO info); ++int Novfs_update_entry( struct inode *i, struct qstr *name, ino_t ino, PENTRY_INFO info); ++void Novfs_remove_inode_entry( struct inode *i, struct qstr *name, ino_t ino); ++void Novfs_free_invalid_entries( struct inode *i ); ++void Novfs_free_inode_cache( struct inode *i ); ++ ++/*===[ Global variables ]=================================================*/ ++struct dentry_operations Novfs_dentry_operations = { ++ .d_revalidate = Novfs_d_revalidate, ++ .d_hash = Novfs_d_hash, ++ .d_compare = Novfs_d_compare, ++ .d_delete = Novfs_d_delete, ++ .d_release = Novfs_d_release, ++ .d_iput = Novfs_d_iput, ++}; ++ ++struct file_operations Novfs_dir_operations = { ++ .owner = THIS_MODULE, ++ .open = Novfs_dir_open, ++ .release = Novfs_dir_release, ++ .llseek = Novfs_dir_lseek, ++ .read = Novfs_dir_read, ++ .readdir = Novfs_dir_readdir, ++ .fsync = Novfs_dir_fsync, ++}; ++ ++static struct file_operations Novfs_file_operations = { ++ .owner = THIS_MODULE, ++ .read = Novfs_f_read, ++ .write = Novfs_f_write, ++ .readdir = Novfs_f_readdir, ++ .ioctl = Novfs_f_ioctl, ++ .mmap = Novfs_f_mmap, ++ .open = Novfs_f_open, ++ .flush = Novfs_f_flush, ++ .release = Novfs_f_release, ++ .fsync = Novfs_f_fsync, ++ .llseek = generic_file_llseek, ++}; ++ ++static struct address_space_operations Novfs_aops = { ++ .readpage = Novfs_a_readpage, ++ .readpages = Novfs_a_readpages, ++ .writepage = Novfs_a_writepage, ++ .writepages = Novfs_a_writepages, ++ .prepare_write = Novfs_a_prepare_write, ++ .commit_write = Novfs_a_commit_write, ++ .set_page_dirty = __set_page_dirty_nobuffers, ++ .direct_IO = Novfs_a_direct_IO, ++}; ++ ++static struct inode_operations Novfs_inode_operations = { ++ .create = Novfs_i_create, ++ .lookup = Novfs_i_lookup, ++ .unlink = Novfs_i_unlink, ++ .mkdir = Novfs_i_mkdir, ++ .rmdir = Novfs_i_rmdir, ++ .mknod = Novfs_i_mknod, ++ .rename = Novfs_i_rename, ++ .setattr = Novfs_i_setattr, ++ .getattr = Novfs_i_getattr, ++}; ++ ++static struct inode_operations Novfs_file_inode_operations = { ++ .setattr = Novfs_i_setattr, ++ .getattr = Novfs_i_getattr, ++}; ++ ++static struct super_operations Novfs_ops = { ++ .read_inode = Novfs_read_inode, ++ .statfs = Novfs_statfs, ++ .clear_inode = Novfs_clear_inode, ++ .drop_inode = generic_delete_inode, ++ .show_options = Novfs_show_options, ++ ++}; ++ ++/* Not currently used ++static struct file_operations Novfs_Control_operations = { ++ .read = Novfs_Control_read, ++ .write = Novfs_Control_write, ++ .ioctl = Novfs_Control_ioctl, ++}; ++*/ ++ ++ino_t Novfs_Inode_Number=1; ++ ++static struct file_system_type Novfs_fs_type = { ++ .name = "novfs", ++ .get_sb = Novfs_get_sb, ++ .kill_sb = Novfs_kill_sb, ++ .owner = THIS_MODULE, ++}; ++ ++struct dentry *Novfs_root=NULL; ++ ++int Novfs_Version_Major=NOVFS_VFS_MAJOR; ++int Novfs_Version_Minor=NOVFS_VFS_MINOR; ++int Novfs_Version_Sub=NOVFS_VFS_SUB; ++int Novfs_Version_Release=NOVFS_VFS_RELEASE; ++ ++char *Novfs_CurrentMount=NULL; ++ ++DECLARE_MUTEX(InodeList_lock); ++ ++LIST_HEAD(InodeList); ++ ++unsigned long InodeCount=0, DCCount=0; ++unsigned long File_update_timeout=FILE_UPDATE_TIMEOUT; ++int PageCache=1; ++ ++/*===[ Code ]=============================================================*/ ++static __inline__ void PRINT_DENTRY(const char *s, struct dentry *d) ++{ ++ DbgPrint("%s: 0x%x\n", s, d); ++ DbgPrint(" d_count: 0x%x\n", d->d_count); ++ DbgPrint(" d_lock: 0x%x\n", d->d_lock); ++ DbgPrint(" d_inode: 0x%x\n", d->d_inode); ++ DbgPrint(" d_lru: 0x%x\n" \ ++ " next: 0x%x\n" \ ++ " prev: 0x%x\n", &d->d_lru, d->d_lru.next, d->d_lru.prev); ++ DbgPrint(" d_child: 0x%x\n" \ ++ " next: 0x%x\n" \ ++ " prev: 0x%x\n", &d->D_CHILD, d->D_CHILD.next, d->D_CHILD.prev); ++ DbgPrint(" d_subdirs: 0x%x\n" \ ++ " next: 0x%x\n" \ ++ " prev: 0x%x\n", &d->d_subdirs, d->d_subdirs.next, d->d_subdirs.prev); ++ DbgPrint(" d_alias: 0x%x\n" \ ++ " next: 0x%x\n" \ ++ " prev: 0x%x\n", &d->d_alias, d->d_alias.next, d->d_alias.prev); ++ DbgPrint(" d_time: 0x%x\n", d->d_time); ++ DbgPrint(" d_op: 0x%x\n", d->d_op); ++ DbgPrint(" d_sb: 0x%x\n", d->d_sb); ++ DbgPrint(" d_flags: 0x%x\n", d->d_flags); ++ DbgPrint(" d_mounted: 0x%x\n", d->d_mounted); ++ DbgPrint(" d_fsdata: 0x%x\n", d->d_fsdata); ++/* DbgPrint(" d_cookie: 0x%x\n", d->d_cookie); */ ++ DbgPrint(" d_parent: 0x%x\n", d->d_parent); ++ DbgPrint(" d_name: 0x%x %.*s\n", &d->d_name, d->d_name.len, d->d_name.name); ++ DbgPrint(" name: 0x%x\n" \ ++ " len: %d\n" \ ++ " hash: 0x%x\n", d->d_name.name, d->d_name.len, d->d_name.hash); ++ DbgPrint(" d_hash: 0x%x\n" \ ++ " next: 0x%x\n" \ ++ " pprev: 0x%x\n", d->d_hash, d->d_hash.next, d->d_hash.pprev); ++} ++ ++/*++======================================================================*/ ++int Novfs_Remove_from_Root(char *RemoveName) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct qstr name; ++ struct dentry *dentry; ++ struct inode *dir; ++ ++ DbgPrint( "Novfs_Remove_from_Root: %s\n", RemoveName); ++ name.len = strlen(RemoveName); ++ name.name = RemoveName; ++ Novfs_d_hash(Novfs_root, &name); ++ ++ dentry = d_lookup( Novfs_root, &name); ++ if (dentry) ++ { ++ if (dentry->d_inode && dentry->d_inode->u.generic_ip) ++ { ++ ((PINODE_DATA)(dentry->d_inode->u.generic_ip))->Scope = NULL; ++ } ++ dput(dentry); ++ } ++ ++ ++ dir = Novfs_root->d_inode; ++ ++ Novfs_lock_inode_cache( dir ); ++ Novfs_remove_inode_entry( dir, &name, 0); ++ Novfs_unlock_inode_cache( dir ); ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_Add_to_Root(char *AddName) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct qstr name; ++ struct inode *dir; ++ ENTRY_INFO info; ++ ino_t ino; ++ ++ DbgPrint( "Novfs_Add_to_Root: %s\n", AddName); ++ name.len = strlen(AddName); ++ name.name = AddName; ++ Novfs_d_hash(Novfs_root, &name); ++ ++ dir = Novfs_root->d_inode; ++ ++ Novfs_lock_inode_cache( dir ); ++ ++ ino = 0; ++ ++ if ( !Novfs_lookup_inode_cache(dir, &name, 0)) ++ { ++ info.mode = S_IFDIR | 0700; ++ info.size = 0; ++ info.atime = info.ctime = info.mtime = CURRENT_TIME; ++ ++ ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); ++ Novfs_add_inode_entry( dir, &name, ino, &info); ++ } ++ ++ Novfs_unlock_inode_cache( dir ); ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_Add_to_Root2(char *AddName) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct dentry *entry; ++ struct qstr name; ++ struct inode *inode; ++ void *scope; ++ ++ DbgPrint( "Novfs_Add_to_Root: %s\n", AddName); ++ name.len = strlen(AddName); ++ name.name = AddName; ++ ++ Novfs_d_hash(Novfs_root, &name); ++ ++ entry = Novfs_d_lookup(Novfs_root, &name); ++ DbgPrint( "Novfs_Add_to_Root: Novfs_d_lookup 0x%x\n", entry); ++ if ( NULL == entry ) ++ { ++ scope = Scope_Lookup(); ++ ++ entry = d_alloc(Novfs_root, &name); ++ DbgPrint( "Novfs_Add_to_Root: d_alloc 0x%x\n", entry ); ++ if (entry) ++ { ++ entry->d_op = &Novfs_dentry_operations; ++ entry->d_time = jiffies+(File_update_timeout*HZ); ++ /* ++ * done in Novfs_d_add now... entry->d_fsdata = (void *)Novfs_internal_hash( &name ); ++ */ ++ inode = Novfs_get_inode(Novfs_root->d_sb, S_IFDIR | 0700, 0, Scope_Get_Uid(scope), 0, &name); ++ DbgPrint( "Novfs_Add_to_Root: Inode=0x%x\n", inode); ++ if (inode) ++ { ++ inode->i_atime = ++ inode->i_ctime = ++ inode->i_mtime = CURRENT_TIME; ++ if ( !Novfs_d_add(Novfs_root, entry, inode, 1)) ++ { ++ if (inode->u.generic_ip) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Flags = USER_INODE; ++ } ++ PRINT_DENTRY("After Novfs_d_add", entry); ++ } ++ else ++ { ++ dput(entry); ++ iput(inode); ++ } ++ } ++ } ++ } ++ else ++ { ++ dput(entry); ++ PRINT_DENTRY("Novfs_Add_to_Root: After dput Dentry", entry); ++ } ++ return(0); ++} ++ ++/*++======================================================================*/ ++char *Novfs_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen) ++/* ++ * Arguments: struct dentry *Dentry - starting entry ++ * char *Buf - pointer to memory buffer ++ * unsigned int Buflen - size of memory buffer ++ * ++ * Returns: pointer to path. ++ * ++ * Abstract: Walks the dentry chain building a path. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *retval=&Buf[Buflen]; ++ struct dentry *p=Dentry; ++ ++ *(--retval) = '\0'; ++ Buflen--; ++ ++ if (!IS_ROOT(p) && !IS_ROOT(p->d_parent)) ++ { ++ while (Buflen && !IS_ROOT(p) && !IS_ROOT(p->d_parent)) ++ { ++ if (Buflen > p->d_name.len) ++ { ++ retval -= p->d_name.len; ++ Buflen -= p->d_name.len; ++ memcpy(retval, p->d_name.name, p->d_name.len); ++ *(--retval) = '\\'; ++ Buflen--; ++ p = p->d_parent; ++ } ++ else ++ { ++ retval = NULL; ++ break; ++ } ++ } ++ } ++ else ++ { ++ *(--retval) = '\\'; ++ } ++ ++ ++ ++if (retval) DbgPrint("Novfs_dget_path: %s\n", retval); ++ return(retval); ++} ++ ++/*++======================================================================*/ ++int verify_dentry( struct dentry *dentry, int Flags ) ++/* ++ * Arguments: struct dentry *dentry - entry to verify ++ * ++ * Returns: zero - Inode cache has been updated. If not in the cache ++ * then file doesn't exist. ++ * !zero - Error ++ * ++ * Abstract: This routine will verify if the file that dentry is pointing ++ * at exist and if it does it will put it in the inode cache of ++ * the parent. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = -ENOENT; ++ struct inode *dir; ++ PENTRY_INFO info=NULL; ++ PINODE_DATA id; ++ session_t session; ++ char *path, *list=NULL, *cp; ++ ino_t ino; ++ struct qstr name; ++ int iLock=0; ++ struct dentry *parent=NULL; ++ u64 ctime; ++ struct inode *inode; ++ ++ if ( IS_ROOT(dentry) ) ++ { ++ DbgPrint("verify_dentry: Root entry\n"); ++ return( 0 ); ++ } ++ ++ if ( dentry && dentry->d_parent && ++ (dir = dentry->d_parent->d_inode) && ++ (id = dir->u.generic_ip) ) ++ { ++ parent = dget_parent(dentry); ++ ++ info = Novfs_Malloc(sizeof(ENTRY_INFO)+PATH_LENGTH_BUFFER, GFP_KERNEL); ++ ++ if (info) ++ { ++ if (Novfs_lock_inode_cache( dir )) ++ { ++ name.len = dentry->d_name.len; ++ name.name = dentry->d_name.name; ++ name.hash = Novfs_internal_hash( &name ); ++ if ( !Novfs_get_entry_time(dir, &name, &ino, info, &ctime)) ++ { ++ inode = dentry->d_inode; ++ if ( inode && ++ ( (inode->i_size != info->size) || ++ (inode->i_mtime.tv_sec != info->mtime.tv_sec) || ++ (inode->i_mtime.tv_nsec != info->mtime.tv_nsec) )) ++ { ++ /* ++ * Values don't match so update. ++ */ ++ ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ } ++ ++ ctime = get_jiffies_64() - ctime; ++ if ( Flags || ctime < (u64)(File_update_timeout*HZ) ) ++ { ++ retVal = 0; ++ Novfs_unlock_inode_cache(dir); ++ dput(parent); ++ Novfs_Free(info); ++ return(0); ++ } ++ } ++ Novfs_unlock_inode_cache(dir); ++ } ++ ++ if ( IS_ROOT(dentry->d_parent) ) ++ { ++ session = Scope_Get_SessionId(Scope_Get_ScopefromName(&dentry->d_name)); ++ } ++ else ++ { ++ session = Scope_Get_SessionId( id->Scope ); ++ } ++ ++ if ( !session ) ++ { ++ id->Scope = Scope_Get_ScopefromPath(dentry); ++ session = Scope_Get_SessionId( id->Scope ); ++ } ++ ++ ino = 0; ++ retVal = 0; ++ ++ if ( IS_ROOT(dentry->d_parent) ) ++ { ++ DbgPrint("verify_dentry: parent is Root directory\n"); ++ list = Scope_Get_ScopeUsers(); ++ ++ iLock = Novfs_lock_inode_cache( dir ); ++ Novfs_invalidate_inode_cache( dir ); ++ ++ if ( list ) ++ { ++ cp = list; ++ while (*cp) ++ { ++ name.name = cp; ++ name.len = strlen(cp); ++ name.hash = Novfs_internal_hash( &name ); ++ cp += (name.len+1); ++ ino = 0; ++ if ( Novfs_get_entry( dir, &name, &ino, info ) ) ++ { ++ info->mode = S_IFDIR | 0700; ++ info->size = 0; ++ info->atime = info->ctime = info->mtime = CURRENT_TIME; ++ ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); ++ Novfs_add_inode_entry(dir, &name, ino, info); ++ } ++ } ++ } ++ Novfs_free_invalid_entries( dir ); ++ } ++ else ++ { ++ ++ path = Novfs_dget_path(dentry, info->name, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ if (dentry->d_name.len <= NW_MAX_PATH_LENGTH) ++ { ++ name.hash = Novfs_internal_hash(&dentry->d_name); ++ name.len = dentry->d_name.len; ++ name.name = dentry->d_name.name; ++ ++ ++ ++ retVal = Novfs_Get_File_Info( path, info, session ); ++ if ( 0 == retVal) ++ { ++ dentry->d_time = jiffies+(File_update_timeout*HZ); ++ iLock = Novfs_lock_inode_cache( dir ); ++ if ( Novfs_update_entry( dir, &name, 0, info ) ) ++ { ++ if (dentry->d_inode) ++ { ++ ino = dentry->d_inode->i_ino; ++ } ++ else ++ { ++ ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); ++ } ++ Novfs_add_inode_entry( dir, &name, ino, info); ++ } ++ if ( dentry->d_inode ) ++ { ++ update_inode(dentry->d_inode, info); ++ id->Flags &= ~UPDATE_INODE; ++ ++ dentry->d_inode->i_flags &= ~S_DEAD; ++ if (dentry->d_inode->u.generic_ip) ++ { ++ ((PINODE_DATA)dentry->d_inode->u.generic_ip)->Scope = id->Scope; ++ } ++ } ++ } ++ else if (-EINTR != retVal) ++ { ++ retVal = 0; ++ iLock = Novfs_lock_inode_cache( dir ); ++ Novfs_remove_inode_entry( dir, &name, 0 ); ++ if ( dentry->d_inode && !(dentry->d_inode->i_flags & S_DEAD) ) ++ { ++ dentry->d_inode->i_flags |= S_DEAD; ++ dentry->d_inode->i_size = 0; ++ dentry->d_inode->i_atime.tv_sec = ++ dentry->d_inode->i_atime.tv_nsec = ++ dentry->d_inode->i_ctime.tv_sec = ++ dentry->d_inode->i_ctime.tv_nsec = ++ dentry->d_inode->i_mtime.tv_sec = ++ dentry->d_inode->i_mtime.tv_nsec = 0; ++ dentry->d_inode->i_blocks = 0; ++ d_delete(dentry); /* Remove from cache */ ++ } ++ } ++ } ++ else ++ { ++ retVal = -ENAMETOOLONG; ++ } ++ } ++ } ++ } ++ else ++ { ++ retVal = -ENOMEM; ++ } ++ if (iLock) ++ { ++ Novfs_unlock_inode_cache( dir ); ++ } ++ dput(parent); ++ } ++ ++ if (list) Novfs_Free(list); ++ if (info) Novfs_Free(info); ++ ++ DbgPrint("verify_dentry: return=0x%x\n", retVal); ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++struct dentry *Novfs_d_lookup(struct dentry *Parent, struct qstr *Name) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ return( d_lookup( Parent, Name)); ++} ++ ++/*++======================================================================*/ ++int Novfs_d_add(struct dentry *Parent, struct dentry *d, struct inode *i, int a) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ void *scope; ++ PINODE_DATA id=NULL; ++ ++ char *path, *buf; ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(d, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ DbgPrint("Novfs_d_add: inode=0x%p ino=%d path %s\n", i, i->i_ino, path); ++ } ++ Novfs_Free(buf); ++ } ++ ++ if ( Parent && Parent->d_inode && Parent->d_inode->u.generic_ip) ++ { ++ id = (PINODE_DATA)Parent->d_inode->u.generic_ip; ++ } ++ ++ if (id && id->Scope) ++ { ++ scope = id->Scope; ++ } ++ else ++ { ++ scope = Scope_Get_ScopefromPath( d ); ++ } ++ ++ ((PINODE_DATA)i->u.generic_ip)->Scope = scope; ++ ++ d->d_time = jiffies+(File_update_timeout*HZ); ++ if (a) ++ { ++ d_add(d, i); ++ } ++ else ++ { ++ d_instantiate(d, i); ++ } ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) ++/* ++ * Arguments: struct dentry *dentry - pointer to dentry to revalidate. ++ * struct nameidata *nd - pointer to nameidata. ++ * ++ * Returns: zero - dentry is not valid. ++ * !zero - valid entry ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = 0; ++ struct inode *dir; ++ PINODE_DATA id; ++ struct qstr name; ++ ++ UNUSED_VARIABLE( nd ); ++ ++ DbgPrint("Novfs_d_revalidate: 0x%p %.*s\n" \ ++ " d_count: %d\n" \ ++ " d_inode: 0x%p\n", ++ dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_count, dentry->d_inode); ++ ++ if (IS_ROOT( dentry )) ++ { ++ retCode = 1; ++ } ++ else ++ { ++ if ( dentry->d_inode && ++ dentry->d_parent && ++ (dir = dentry->d_parent->d_inode) && ++ (id = dir->u.generic_ip) ) ++ { ++ /* ++ * Check timer to see if in valid time limit ++ */ ++ if (jiffies > dentry->d_time) ++ { ++ /* ++ * Revalidate entry ++ */ ++ name.len = dentry->d_name.len; ++ name.name = dentry->d_name.name; ++ name.hash = Novfs_internal_hash(&dentry->d_name); ++ dentry->d_time = 0; ++ ++ if ( 0 == verify_dentry( dentry, 0 )) ++ { ++ if (Novfs_lock_inode_cache( dir )) ++ { ++ if (Novfs_lookup_inode_cache( dir, &name, 0)) ++ { ++ dentry->d_time = jiffies + (File_update_timeout*HZ); ++ retCode = 1; ++ } ++ Novfs_unlock_inode_cache( dir ); ++ } ++ } ++ } ++ else ++ { ++ retCode = 1; ++ } ++ } ++ } ++ ++ ++ if ( ( 0 == retCode ) && dentry->d_inode ) ++ { ++ /* ++ * Entry has become invalid ++ */ ++/* dput(dentry); ++*/ ++ } ++ ++ DbgPrint("Novfs_d_revalidate: return 0x%x\n", retCode); ++ ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++unsigned long Novfs_internal_hash (struct qstr *name) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ unsigned long hash = 0; ++ unsigned int len = name->len; ++ unsigned char *c = (unsigned char *)name->name; ++ ++ while(len--) ++ { ++ /* ++ * Lower case values for the hash. ++ */ ++ hash = partial_name_hash(tolower(*c++), hash); ++ } ++ ++ return(hash); ++} ++ ++/*++======================================================================*/ ++int Novfs_d_hash (struct dentry *dentry, struct qstr *name) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ UNUSED_VARIABLE( dentry ); ++ ++ DbgPrint("Novfs_d_hash: %.*s\n", name->len, name->name); ++ ++ name->hash = Novfs_internal_hash( name ); ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_d_strcmp (struct qstr *s1, struct qstr *s2) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = 1; ++ unsigned char *str1, *str2; ++ unsigned int len; ++ ++ DbgPrint("Novfs_d_strcmp: s1=%.*s s2=%.*s\n", s1->len, s1->name, s2->len, s2->name); ++ ++ if (s1->len && (s1->len == s2->len) && (s1->hash == s2->hash) ) ++ { ++ len = s1->len; ++ str1 = (unsigned char *)s1->name; ++ str2 = (unsigned char *)s2->name; ++ for ( retCode = 0; len-- ; str1++, str2++ ) ++ { ++ if (*str1 != *str2) ++ { ++ if (tolower(*str1) != tolower(*str2)) ++ { ++ retCode = 1; ++ break; ++ } ++ } ++ } ++ } ++ ++ DbgPrint("Novfs_d_strcmp: retCode=0x%x\n", retCode); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_d_compare (struct dentry *parent, struct qstr *s1, struct qstr *s2) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode; ++ ++ retCode = Novfs_d_strcmp(s1, s2); ++ ++ DbgPrint("Novfs_d_compare: retCode=0x%x\n", retCode); ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_d_delete(struct dentry *dentry) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = 0; ++ ++ DbgPrint("Novfs_d_delete: 0x%p %.*s\n" \ ++ " d_count: %d\n" \ ++ " d_inode: 0x%p\n", ++ dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_count, dentry->d_inode); ++ ++ if (dentry->d_inode && (dentry->d_inode->i_flags & S_DEAD)) ++ { ++ retVal = 1; ++ } ++ ++ dentry->d_time = 0; ++ ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++void Novfs_d_release(struct dentry *dentry) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DbgPrint("Novfs_d_release: 0x%x %.*s\n", dentry, dentry->d_name.len, dentry->d_name.name); ++} ++ ++/*++======================================================================*/ ++void Novfs_d_iput(struct dentry *dentry, struct inode *inode) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DbgPrint("Novfs_d_iput: Inode=0x%x Ino=%d Dentry=0x%x Name=%.*s\n", ++ inode, inode->i_ino, dentry, dentry->d_name.len, dentry->d_name.name); ++ ++ iput(inode); ++ ++} ++/*++======================================================================*/ ++int Novfs_dir_open(struct inode *dir, struct file *file) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *path, *buf; ++ ++ ++ DbgPrint("Novfs_dir_open: Inode 0x%x %d Name %.*s\n", dir, dir->i_ino, file->f_dentry->d_name.len, file->f_dentry->d_name.name); ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ DbgPrint("Novfs_dir_open: path %s\n", path); ++ } ++ Novfs_Free(buf); ++ } ++ file->private_data = NULL; ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_dir_release(struct inode *dir, struct file *file) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct inode *inode; ++ ++ DbgPrint("Novfs_dir_release: Inode 0x%x %d Name %.*s\n", dir, dir->i_ino, file->f_dentry->d_name.len, file->f_dentry->d_name.name); ++ if (file->private_data) ++ { ++ inode = file->private_data; ++ Novfs_free_inode_cache( inode ); ++ Novfs_Free(file->private_data); ++ } ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++loff_t Novfs_dir_lseek(struct file *file, loff_t offset, int origin) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ return(default_llseek(file, offset, origin)); ++} ++ ++/*++======================================================================*/ ++int Novfs_dir_read(struct file *file, char *buf, size_t len, loff_t *off) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++/* ++ int rlen = 0; ++ ++ DbgPrint("Novfs_dir_readdir: dentry path %.*s buf=0x%p len=%d off=%lld\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, buf, len, *off); ++ ++ if (0 == *off) ++ { ++ rlen = 8; ++ rlen -= copy_to_user(buf, "Testing\n", 8); ++ *off += rlen; ++ } ++ return(rlen); ++*/ ++ return(generic_read_dir(file, buf, len, off)); ++} ++ ++/*++======================================================================*/ ++void process_list(struct file *File, char *List, int Type, PENTRY_INFO Info, session_t SessionId) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ unsigned char *path, *buf=NULL, *cp; ++ struct inode *dir = File->f_dentry->d_inode; ++ struct qstr name; ++ ino_t ino=0; ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ path = buf; ++ if (buf) ++ { ++ path = Novfs_dget_path(File->f_dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ strcpy(buf, path); ++ } ++ path = buf+strlen(buf); ++ *path++ = '\\'; ++ } ++ ++ if ( List ) ++ { ++ cp = List; ++ while (*cp) ++ { ++ name.name = cp; ++ name.len = strlen(cp); ++ name.hash = Novfs_internal_hash( &name ); ++ cp += (name.len+1); ++ ++ Info->mode = S_IFDIR | 0700; ++ Info->size = 0; ++ Info->atime = Info->ctime = Info->mtime = CURRENT_TIME; ++ ++ if ( (USER_LIST != Type) && buf && ((int)(path-buf)+name.len < PATH_LENGTH_BUFFER) ) ++ { ++ strcpy(path, name.name); ++ Novfs_Get_File_Info(buf, Info, SessionId); ++ } ++ ++ if ( Novfs_update_entry( dir, &name, ino, Info ) ) ++ { ++ Novfs_add_inode_entry(dir, &name, (ino_t)InterlockedIncrement(&Novfs_Inode_Number), Info); ++ } ++ } ++ } ++ ++ if (buf) Novfs_Free(buf); ++ ++} ++ ++/*++======================================================================*/ ++int Novfs_dir_readdir(struct file * file, void * dirent, filldir_t filldir) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ unsigned char *path, *buf=NULL; ++ unsigned char *list=NULL; ++ PENTRY_INFO info=NULL, pinfo, iinfo; ++ int count; ++ ++ int status = -ENOMEM; ++ struct inode *inode; ++ session_t sessionId; ++ uid_t uid; ++ struct qstr name; ++ struct list_head *inter; ++ ino_t ino; ++ int iLock=0; ++ int type = 0; ++ ++ DbgPrint("Novfs_dir_readdir(%s): dentry path %.*s 0x%x\n", current->comm, file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_dentry->d_fsdata); ++ ++ inode = file->f_dentry->d_inode; ++ ++ info = Novfs_Malloc(sizeof(ENTRY_INFO)+PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (info) ++ { ++ if (!file->private_data) ++ { ++ if ( inode && inode->u.generic_ip ) ++ { ++ sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ if (0 == sessionId) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath(file->f_dentry); ++ sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ uid = Scope_Get_Uid(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ else ++ { ++ sessionId = 0; ++ uid = current->euid; ++ } ++ ++ if ( IS_ROOT(file->f_dentry) || /* Root */ ++ IS_ROOT(file->f_dentry->d_parent) || /* User */ ++ IS_ROOT(file->f_dentry->d_parent->d_parent) ) /* Server */ ++ { ++ if ( IS_ROOT(file->f_dentry) ) ++ { ++ DbgPrint("Novfs_dir_readdir: Root directory\n"); ++ list = Scope_Get_ScopeUsers(); ++ type = USER_LIST; ++ ++ } ++ else if ( IS_ROOT(file->f_dentry->d_parent) ) ++ { ++ DbgPrint("Novfs_dir_readdir: Parent is Root directory\n"); ++ Novfs_Get_Connected_Server_List( &list, sessionId ); ++ type = SERVER_LIST; ++ } ++ else ++ { ++ DbgPrint("Novfs_dir_readdir: Parent-Parent is Root directory\n"); ++ Novfs_Get_Server_Volume_List(&file->f_dentry->d_name, &list, sessionId); ++ type = VOLUME_LIST; ++ } ++ ++ iLock = Novfs_lock_inode_cache( inode ); ++ Novfs_invalidate_inode_cache( inode ); ++ ++ process_list(file, list, type, info, sessionId); ++ } ++ else ++ { ++ DbgPrint("Novfs_dir_readdir: Default directory\n"); ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(file->f_dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ unsigned long enumHandle=0; ++ ++ iLock = Novfs_lock_inode_cache( inode ); ++ Novfs_invalidate_inode_cache(inode); ++ do ++ { ++ /* ++ * Novfs_Get_Directory_List will return 0 when no error or -1 when ++ * the last entry is returned. Otherwise it will return an error. ++ */ ++ info->namelength = 0; ++ status = Novfs_Get_Directory_ListEx(path, &enumHandle, &count, &pinfo, sessionId); ++ DbgPrint("Novfs_dir_readdir: Novfs_Get_Directory_List return 0x%x count=%d pinfo=0x%p\n", status, count, pinfo); ++ iinfo = pinfo; ++ while ( (0 == status) && pinfo && count-- ) ++ { ++ memcpy(info, pinfo, (int)((char *)&pinfo->name[pinfo->namelength]-(char *)pinfo)); ++ pinfo = (PENTRY_INFO)&pinfo->name[pinfo->namelength]; ++ name.len = info->namelength; ++ name.name = info->name; ++ name.hash = Novfs_internal_hash(&name); ++ info->name[name.len] = '\0'; ++ ++ DbgPrint("Novfs_dir_readdir: Got %s\n", name.name); ++ ++ if ( Novfs_update_entry( inode, &name, 0, info )) ++ { ++ Novfs_add_inode_entry(inode, &name, (ino_t)InterlockedIncrement(&Novfs_Inode_Number), info); ++ } ++ } ++ ++ if (iinfo) ++ { ++ Novfs_Free(iinfo); ++ } ++ ++ } ++ while ( !status ); ++ } ++ } ++ } ++ ++ file->private_data = (PDIR_CACHE)Novfs_Malloc(sizeof(struct inode) + sizeof(DIR_CACHE), GFP_KERNEL); ++ if (file->private_data) ++ { ++ struct inode *dinode = file->private_data; ++ PINODE_DATA id = (PINODE_DATA)((char *)file->private_data+sizeof(struct inode)); ++ ++ dinode->u.generic_ip = id; ++ ++ id->Scope = ((PINODE_DATA)inode->u.generic_ip)->Scope; ++ id->Flags = 0; ++ INIT_LIST_HEAD( &id->DirCache ); ++ init_MUTEX( &id->DirCacheLock ); ++ ++ inter = NULL; ++ /* ++ * Copy rest of the files. ++ */ ++ while( !Novfs_enumerate_inode_cache(inode, &inter, &ino, info)) ++ { ++ DbgPrint("Novfs_dir_readdir : BEGIN Calling filedir %llu with ino %d mode 0%o name %s\n", file->f_pos, ino, info->mode, info->name); ++ name.len = info->namelength; ++ name.name = info->name; ++ name.hash = Novfs_internal_hash( &name ); ++ Novfs_add_inode_entry(dinode, &name, ino, info); ++ DbgPrint("Novfs_dir_readdir : END Calling filedir %llu with ino %d mode 0%o name %s\n", file->f_pos, ino, info->mode, info->name); ++ } ++ file->private_data = dinode; ++ } ++ ++ if ( iLock ) ++ { ++ Novfs_free_invalid_entries( inode ); ++ } ++ } ++ ++ switch ((int) file->f_pos) ++ { ++ case 0: ++ DbgPrint("Novfs_dir_readdir : Calling filedir %llu with ino %d name .\n", file->f_pos, inode->i_ino); ++ if (filldir(dirent, ".", 1, file->f_pos, inode->i_ino, DT_DIR) < 0) ++ { ++ break; ++ } ++ file->f_pos++; ++ /* fallthrough */ ++ case 1: ++ DbgPrint("Novfs_dir_readdir : Calling filedir %llu with ino %d name ..\n", file->f_pos, parent_ino(file->f_dentry)); ++ if (filldir(dirent, "..", 2, file->f_pos, parent_ino(file->f_dentry), DT_DIR) < 0) ++ { ++ break; ++ } ++ file->f_pos++; ++ /* fallthrough */ ++ } ++ ++ status = 0; ++ inter = NULL; ++ ++ if(!Novfs_get_entry_by_pos(file->private_data, file->f_pos, &ino, info)) ++ { ++ DbgPrint("Novfs_dir_readdir : Calling filedir %llu with ino %d mode 0%o name %s\n", file->f_pos, ino, info->mode, info->name); ++ filldir(dirent, info->name, info->namelength, file->f_pos, ino, info->mode >> 12); ++ } ++ file->f_pos++; ++ ++ if (iLock) ++ { ++ Novfs_unlock_inode_cache(inode); ++ } ++ } ++ ++ if (info) Novfs_Free( info ); ++ if (buf) Novfs_Free( buf ); ++ if (list) Novfs_Free( list ); ++ ++ return(status); ++} ++ ++ ++/*++======================================================================*/ ++int Novfs_dir_fsync(struct file * file, struct dentry *dentry, int datasync) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ return(simple_sync_file(file, dentry, datasync)); ++} ++ ++ ++/*++======================================================================*/ ++ssize_t Novfs_f_read(struct file *file, char *buf, size_t len, loff_t *off) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ size_t thisread, totalread=0; ++ loff_t offset = *off; ++ struct inode *inode; ++ session_t session; ++ PINODE_DATA id; ++ ++ if ( file->f_dentry && ++ (inode = file->f_dentry->d_inode) && ++ (id = (PINODE_DATA)inode->u.generic_ip)) ++ { ++ ++ DbgPrint("Novfs_f_read(0x%x 0x%p %d %lld %.*s)\n", ++ (unsigned long)file->private_data, ++ buf, len, offset, ++ file->f_dentry->d_name.len, ++ file->f_dentry->d_name.name); ++ ++ if ( PageCache && ++ !(file->f_flags & O_DIRECT) && ++ id->CacheFlag ) ++ { ++ totalread = generic_file_read(file, buf, len, off); ++ } ++ else ++ { ++ session = Scope_Get_SessionId(id->Scope); ++ if (0 == session) ++ { ++ id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(id->Scope); ++ } ++ ++ while(len > 0 && (offset < i_size_read(inode)) ) ++ { ++ thisread = len; ++ if (Novfs_Read_File((unsigned long)file->private_data, buf, &thisread, &offset, session) || !thisread) ++ { ++ break; ++ } ++ DbgPrint("Novfs_f_read thisread = 0x%x\n", thisread); ++ len -= thisread; ++ buf += thisread; ++ offset += thisread; ++ totalread += thisread; ++ } ++ *off = offset; ++ } ++ } ++ DbgPrint("Novfs_f_read return = 0x%x\n", totalread); ++ ++ return(totalread); ++} ++ ++/*++======================================================================*/ ++ssize_t Novfs_f_write(struct file *file, const char *buf, size_t len, loff_t *off) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ssize_t thiswrite, totalwrite=0; ++ loff_t offset = *off; ++ session_t session; ++ struct inode *inode; ++ int status; ++ PINODE_DATA id; ++ ++ if ( file->f_dentry && ++ (inode = file->f_dentry->d_inode) && ++ (id = file->f_dentry->d_inode->u.generic_ip) ) ++ { ++ DbgPrint("Novfs_f_write(0x%x %d %lld %.*s)\n", (unsigned long)file->private_data, len, offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name); ++ ++ if ( PageCache && ++ !(file->f_flags & O_DIRECT) && ++ id->CacheFlag ) ++ { ++ totalwrite = generic_file_write(file, buf, len, off); ++ } ++ else ++ { ++ if (file->f_flags & O_APPEND) ++ { ++ offset = i_size_read(inode); ++ DbgPrint("Novfs_f_write appending to end %lld %.*s\n", offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name); ++ } ++ ++ session = Scope_Get_SessionId(id->Scope); ++ if (0 == session) ++ { ++ id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(id->Scope); ++ } ++ ++ while(len > 0) ++ { ++ thiswrite = len; ++ if ((status = Novfs_Write_File( ++ (unsigned long)file->private_data, ++ (unsigned char *)buf, ++ &thiswrite, ++ &offset, ++ session)) || !thiswrite) ++ { ++ totalwrite = status; ++ break; ++ } ++ DbgPrint("Novfs_f_write thiswrite = 0x%x\n", thiswrite); ++ len -= thiswrite; ++ buf += thiswrite; ++ offset += thiswrite; ++ totalwrite += thiswrite; ++ if (offset > i_size_read(inode)) ++ { ++ i_size_write(inode, offset); ++ inode->i_blocks = (offset + inode->i_blksize - 1) >> inode->i_blkbits; ++ } ++ inode->i_mtime = inode->i_atime = CURRENT_TIME; ++ id->Flags |= UPDATE_INODE; ++ ++ } ++ *off = offset; ++ } ++ } ++ DbgPrint("Novfs_f_write return = 0x%x\n", totalwrite); ++ ++ return(totalwrite); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_readdir(struct file *file, void *data, filldir_t fill) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(data); ++ UNUSED_VARIABLE(fill); ++ return(-EISDIR); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ UNUSED_VARIABLE(inode); ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(cmd); ++ UNUSED_VARIABLE(arg); ++ DbgPrint("Novfs_f_ioctl: file=0x%x cmd=0x%x arg=0x%x", file, cmd, arg); ++ ++ return(-ENOSYS); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_mmap(struct file * file, struct vm_area_struct * vma) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -EINVAL; ++ ++ DbgPrint("Novfs_f_mmap: file=0x%x", file); ++ ++ retCode = generic_file_mmap(file, vma); ++ ++ DbgPrint("Novfs_f_mmap: retCode=0x%x\n", retCode); ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_open(struct inode *inode, struct file *file) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PENTRY_INFO info=NULL; ++ int retCode = -ENOENT; ++ session_t session; ++ char *path; ++ struct dentry *parent; ++ ino_t ino; ++ PINODE_DATA id; ++ ++ DbgPrint("Novfs_f_open: inode=0x%p file=0x%p dentry=0x%p dentry->d_inode=0x%p\n", inode, file, file->f_dentry, file->f_dentry->d_inode); ++ if (file->f_dentry) ++ { ++ DbgPrint("Novfs_f_open: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode); ++ } ++ ++ if (inode && inode->u.generic_ip) ++ { ++ id = (PINODE_DATA)file->f_dentry->d_inode->u.generic_ip; ++ session = Scope_Get_SessionId(id->Scope); ++ if (0 == session) ++ { ++ id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(id->Scope); ++ } ++ ++ info = (PENTRY_INFO)Novfs_Malloc(sizeof(ENTRY_INFO) + PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (info) ++ { ++ path = Novfs_dget_path(file->f_dentry, info->name, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ DbgPrint("Novfs_f_open: %s\n", path); ++ retCode = Novfs_Open_File( ++ path, ++ file->f_flags & ~O_EXCL, info, ++ (unsigned long *)&file->private_data, ++ session); ++ if ( !retCode ) ++ { ++ /* ++ *update_inode(inode, &info); ++ */ ++ id->FileHandle = (unsigned long)file->private_data; ++ id->CacheFlag = Novfs_Get_File_Cache_Flag( path, session ); ++ ++ if( !Novfs_Get_File_Info(path, info, session)) ++ { ++ update_inode(inode, info); ++ } ++ ++ parent = dget_parent(file->f_dentry); ++ ++ if (parent && parent->d_inode) ++ { ++ struct inode *dir = parent->d_inode; ++ Novfs_lock_inode_cache(dir); ++ ino = 0; ++ if (Novfs_get_entry(dir, &file->f_dentry->d_name, &ino, info)) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ } ++ ++ Novfs_unlock_inode_cache(dir); ++ } ++ dput(parent); ++ } ++ } ++ Novfs_Free(info); ++ } ++ } ++ DbgPrint("Novfs_f_open: retCode=0x%x\n", retCode); ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_flush(struct file *file) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct inode *inode; ++ ++ if (file->f_dentry) ++ { ++ if( (file->f_flags & O_ACCMODE) != O_RDONLY) ++ { ++ inode = file->f_dentry->d_inode; ++ DbgPrint("Novfs_f_flush: %.*s f_flags=0x%x f_mode=0%o i_mode=0%o\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode); ++ filemap_fdatawrite( file->f_dentry->d_inode->i_mapping ); ++ } ++ } ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_release(struct inode *inode, struct file *file) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -EACCES; ++ session_t session; ++ PINODE_DATA id; ++ ++ DbgPrint("Novfs_f_release: path=%.*s handle=%x\n", ++ file->f_dentry->d_name.len, ++ file->f_dentry->d_name.name, ++ (unsigned long)file->private_data); ++ ++ if ( file->f_dentry->d_inode && (id = file->f_dentry->d_inode->u.generic_ip)) ++ { ++ session = Scope_Get_SessionId(id->Scope); ++ if (0 == session) ++ { ++ id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(id->Scope); ++ } ++ ++ //invalidate_remote_inode(file->f_dentry->d_inode); ++ ++ retCode = Novfs_Close_File((unsigned long)file->private_data, session); ++ id->FileHandle = 0; ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_fsync(struct file *file, struct dentry *dentry, int datasync) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(dentry); ++ UNUSED_VARIABLE(datasync); ++ return(0); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_llseek(struct file *file, loff_t offset, int origin) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ DbgPrint("Novfs_f_llseek: File=0x%x Name=%.*s offset=%lld origin=%d\n", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, offset, origin); ++ return(generic_file_llseek(file, offset, origin)); ++} ++ ++/*++======================================================================*/ ++int Novfs_f_lock(struct file *file, int cmd, struct file_lock *lock) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(cmd); ++ UNUSED_VARIABLE(lock); ++ return(-ENOSYS); ++} ++/*++======================================================================*/ ++static void Novfs_copy_cache_pages(struct address_space *mapping, ++ struct list_head *pages, int bytes_read, char *data, ++ struct pagevec *plru_pvec) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct page *page; ++ char *target; ++ ++ while (bytes_read > 0) { ++ if (list_empty(pages)) ++ break; ++ ++ page = list_entry(pages->prev, struct page, lru); ++ list_del(&page->lru); ++ ++ if (add_to_page_cache(page, mapping, page->index, ++ GFP_KERNEL)) { ++ page_cache_release(page); ++ data += PAGE_CACHE_SIZE; ++ bytes_read -= PAGE_CACHE_SIZE; ++ continue; ++ } ++ ++ target = kmap_atomic(page,KM_USER0); ++ ++ if (PAGE_CACHE_SIZE > bytes_read) { ++ memcpy(target, data, bytes_read); ++ /* zero the tail end of this partial page */ ++ memset(target + bytes_read, 0, ++ PAGE_CACHE_SIZE - bytes_read); ++ bytes_read = 0; ++ } else { ++ memcpy(target, data, PAGE_CACHE_SIZE); ++ bytes_read -= PAGE_CACHE_SIZE; ++ } ++ kunmap_atomic(target, KM_USER0); ++ ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ unlock_page(page); ++ if (!pagevec_add(plru_pvec, page)) ++ __pagevec_lru_add(plru_pvec); ++ data += PAGE_CACHE_SIZE; ++ } ++ return; ++} ++ ++/*++======================================================================*/ ++int Novfs_a_writepage(struct page* page, struct writeback_control *wbc) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -EFAULT; ++ struct inode *inode = page->mapping->host; ++ PINODE_DATA id = inode->u.generic_ip; ++ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT); ++ session_t session=0; ++ DATA_LIST dlst[2]; ++ size_t len = PAGE_CACHE_SIZE; ++ ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ++ page_cache_get(page); ++ ++ pos = ((loff_t)page->index << PAGE_CACHE_SHIFT); ++ ++ /* ++ * Leave first dlst entry for reply header. ++ */ ++ dlst[1].page = page; ++ dlst[1].offset = NULL; ++ dlst[1].len = len; ++ dlst[1].rwflag = DLREAD; ++ ++ /* ++ * Check size so we don't write pass end of file. ++ */ ++ if ((pos + (loff_t)len) > i_size_read(inode)) ++ { ++ len = (size_t)(i_size_read(inode) - pos); ++ } ++ ++ retCode = Novfs_Write_Pages( id->FileHandle, dlst, 2, len, pos, session); ++ if ( !retCode ) ++ { ++ SetPageUptodate(page); ++ } ++ ++ unlock_page(page); ++ page_cache_release(page); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_a_writepages(struct address_space *mapping, struct writeback_control *wbc) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = 0; ++ struct inode *inode=mapping->host; ++ session_t session=0; ++ unsigned long fh=0; ++ ++ int max_page_lookup = MaxIoSize/PAGE_CACHE_SIZE; ++ ++ PDATA_LIST dlist, dlptr; ++ struct page **pages; ++ ++ int dlist_idx, i=0; ++ pgoff_t index, next_index=0; ++ loff_t pos=0; ++ size_t tsize; ++ ++ DbgPrint("Novfs_a_writepages: mapping=0x%p wbc=0x%p\n", mapping, wbc); ++ ++ if (inode) ++ { ++ DbgPrint(" Inode=0x%x Ino=%d\n", inode, inode->i_ino); ++ ++ if (inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ fh = ((PINODE_DATA)inode->u.generic_ip)->FileHandle; ++ } ++ } ++ ++ dlist = Novfs_Malloc( sizeof(DATA_LIST) * max_page_lookup, GFP_KERNEL); ++ pages = Novfs_Malloc( sizeof(struct page *) * max_page_lookup, GFP_KERNEL); ++ ++ if ( fh && dlist && pages ) ++ { ++ struct backing_dev_info *bdi = mapping->backing_dev_info; ++ int done = 0; ++ int nr_pages=0; ++ int scanned = 0; ++ ++ if (wbc->nonblocking && bdi_write_congested(bdi)) ++ { ++ wbc->encountered_congestion = 1; ++ return 0; ++ } ++ ++ if (wbc->sync_mode == WB_SYNC_NONE) ++ { ++ index = mapping->writeback_index; /* Start from prev offset */ ++ } ++ else ++ { ++ index = 0; /* whole-file sweep */ ++ scanned = 1; ++ } ++ ++ next_index = index; ++ ++ while (!done && (wbc->nr_to_write > 0)) ++ { ++ dlist_idx = 0; ++ dlptr = &dlist[1]; ++ ++ DbgPrint("Novfs_a_writepages1: nr_pages=%d\n", nr_pages); ++ if ( !nr_pages ) ++ { ++ memset(pages, 0, sizeof(struct page *)*max_page_lookup); ++ ++ AS_TREE_LOCK(&mapping->tree_lock); ++ ++ /* ++ * Need to ask for one less then max_page_lookup or we ++ * will overflow the request buffer. This also frees ++ * the first entry for the reply buffer. ++ */ ++ nr_pages = radix_tree_gang_lookup_tag(&mapping->page_tree, ++ (void **)pages, index, max_page_lookup-1, PAGECACHE_TAG_DIRTY); ++ ++ DbgPrint("Novfs_a_writepages2: nr_pages=%d\n", nr_pages); ++ ++ ++ for (i = 0; i < nr_pages; i++) ++ { ++ page_cache_get(pages[i]); ++ } ++ ++ AS_TREE_UNLOCK(&mapping->tree_lock); ++ ++ if (nr_pages) ++ { ++ index = pages[nr_pages - 1]->index + 1; ++ pos = (loff_t)pages[0]->index << PAGE_CACHE_SHIFT; ++ } ++ ++ if ( !nr_pages ) ++ { ++ if ( scanned ) ++ { ++ index = 0; ++ scanned = 0; ++ continue; ++ } ++ done = 1; ++ } ++ else ++ { ++ next_index = pages[0]->index; ++ i = 0; ++ } ++ } ++ else ++ { ++ if (pages[i]) ++ { ++ pos = (loff_t)pages[i]->index << PAGE_CACHE_SHIFT; ++ } ++ } ++ ++ ++ for ( ; i < nr_pages ; i++) ++ { ++ struct page *page = pages[i]; ++ ++ /* ++ * At this point we hold neither mapping->tree_lock nor ++ * lock on the page itself: the page may be truncated or ++ * invalidated (changing page->mapping to NULL), or even ++ * swizzled back from swapper_space to tmpfs file ++ * mapping ++ */ ++ ++ DbgPrint("Novfs_a_writepages: pos=0x%llx index=%d page->index=%d next_index=%d\n", pos, index, page->index, next_index); ++ ++ if (page->index != next_index) ++ { ++ next_index = page->index; ++ break; ++ } ++ next_index = page->index+1; ++ ++ lock_page(page); ++ ++ if (wbc->sync_mode != WB_SYNC_NONE) ++ wait_on_page_writeback(page); ++ ++ if (page->mapping != mapping || PageWriteback(page) || ++ !clear_page_dirty_for_io(page)) ++ { ++ unlock_page(page); ++ continue; ++ } ++ ++ dlptr[dlist_idx].page = page; ++ dlptr[dlist_idx].offset = NULL; ++ dlptr[dlist_idx].len = PAGE_CACHE_SIZE; ++ dlptr[dlist_idx].rwflag = DLREAD; ++ dlist_idx++; ++ DbgPrint("Novfs_a_writepages: Add page=0x%p index=0x%lx\n", page, page->index); ++ } ++ ++ DbgPrint("Novfs_a_writepages: dlist_idx=%d\n", dlist_idx); ++ if ( dlist_idx ) ++ { ++ tsize = dlist_idx * PAGE_CACHE_SIZE; ++ /* ++ * Check size so we don't write pass end of file. ++ */ ++ if ((pos + tsize) > i_size_read(inode)) ++ { ++ tsize = (size_t)(i_size_read(inode) - pos); ++ } ++ ++ retCode = Novfs_Write_Pages(fh, dlist, dlist_idx+1, tsize, pos, session); ++ switch (retCode) ++ { ++ case 0: ++ wbc->nr_to_write -= dlist_idx; ++ break; ++ ++ case -ENOSPC: ++ set_bit(AS_ENOSPC, &mapping->flags); ++ done = 1; ++ break; ++ ++ default: ++ set_bit(AS_EIO, &mapping->flags); ++ done = 1; ++ break; ++ } ++ ++ do ++ { ++ unlock_page((struct page *)dlptr[dlist_idx-1].page); ++ page_cache_release((struct page *)dlptr[dlist_idx-1].page); ++ DbgPrint("Novfs_a_writepages: release page=0x%p index=0x%lx\n", dlptr[dlist_idx-1].page, ((struct page *)dlptr[dlist_idx-1].page)->index); ++ if ( !retCode ) ++ { ++ wbc->nr_to_write--; ++ } ++ } while( --dlist_idx ); ++ } ++ ++ if ( i >= nr_pages ) ++ { ++ nr_pages = 0; ++ } ++ } ++ ++ mapping->writeback_index = index; ++ ++ } ++ else ++ { ++ set_bit(AS_EIO, &mapping->flags); ++ } ++ if (dlist) Novfs_Free(dlist); ++ if (pages) Novfs_Free(pages); ++ ++ DbgPrint("Novfs_a_writepage: retCode=%d\n", retCode); ++ return (0); ++ ++} ++ ++/*++======================================================================*/ ++int Novfs_a_readpage(struct file *file, struct page *page) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = 0; ++ void *pbuf; ++ struct inode *inode=NULL; ++ struct dentry *dentry=NULL; ++ loff_t offset; ++ size_t len; ++ session_t session=0; ++ ++ DbgPrint("Novfs_a_readpage: File=0x%x Name=%.*s Page=0x%x", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, page); ++ ++ dentry = file->f_dentry; ++ ++ if (dentry) ++ { ++ DbgPrint(" Dentry=0x%x Name=%.*s", dentry, dentry->d_name.len, dentry->d_name.name); ++ if (dentry->d_inode) ++ { ++ inode = dentry->d_inode; ++ } ++ } ++ ++ ++ ++ if (inode) ++ { ++ DbgPrint(" Inode=0x%x Ino=%d", inode, inode->i_ino); ++ ++ if (inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ } ++ } ++ ++ DbgPrint("\n"); ++ ++ ++ if (!PageUptodate(page)) ++ { ++ DATA_LIST dlst[2]; ++ ++ offset = page->index << PAGE_CACHE_SHIFT; ++ len = PAGE_CACHE_SIZE; ++ ++ /* ++ * Save the first entry for the reply header. ++ */ ++ dlst[1].page = page; ++ dlst[1].offset = NULL; ++ dlst[1].len = PAGE_CACHE_SIZE; ++ dlst[1].rwflag = DLWRITE; ++ ++ retCode = Novfs_Read_Pages((unsigned long)file->private_data, dlst, 2, &len, &offset, session); ++ if ( len && (len < PAGE_CACHE_SIZE) ) ++ { ++ pbuf = kmap_atomic(page, KM_USER0); ++ memset(&((char *)pbuf)[len], 0, PAGE_CACHE_SIZE-len); ++ kunmap_atomic(pbuf, KM_USER0); ++ } ++ ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ } ++ unlock_page(page); ++ ++ DbgPrint("Novfs_a_readpage: retCode=%d\n", retCode); ++ return (retCode); ++ ++} ++ ++/*++======================================================================*/ ++int Novfs_a_readpages(struct file *file, struct address_space *mapping, struct list_head *page_lst, unsigned nr_pages) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = 0; ++ struct inode *inode=NULL; ++ struct dentry *dentry=NULL; ++ session_t session=0; ++ loff_t offset; ++ size_t len; ++ ++ unsigned page_idx; ++ struct pagevec lru_pvec; ++ pgoff_t next_index; ++ ++ char *rbuf, done=0; ++ ++ DbgPrint("Novfs_a_readpages: File=0x%p Name=%.*s Pages=%d\n", file, file->f_dentry->d_name.len, file->f_dentry->d_name.name, nr_pages); ++ ++ dentry = file->f_dentry; ++ ++ if (dentry) ++ { ++ DbgPrint(" Dentry=0x%x Name=%.*s\n", dentry, dentry->d_name.len, dentry->d_name.name); ++ if (dentry->d_inode) ++ { ++ inode = dentry->d_inode; ++ } ++ } ++ ++ if (inode) ++ { ++ DbgPrint(" Inode=0x%x Ino=%d\n", inode, inode->i_ino); ++ ++ if (inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ } ++ } ++ ++ rbuf = (char *)Novfs_Malloc(MaxIoSize, GFP_KERNEL); ++ if (rbuf) ++ { ++ pagevec_init(&lru_pvec, 0); ++ for (page_idx = 0; page_idx < nr_pages && !done; ) ++ { ++ struct page *page, *tpage; ++ ++ if (list_empty(page_lst)) ++ break; ++ ++ page = list_entry(page_lst->prev, struct page, lru); ++ ++ next_index = page->index; ++ offset = (loff_t)page->index << PAGE_CACHE_SHIFT; ++ len = 0; ++ ++ /* ++ * Count number of contiguous pages. ++ */ ++ list_for_each_entry_reverse(tpage, page_lst, lru) ++ { ++ if ( (next_index != tpage->index) || ++ (len >= MaxIoSize-PAGE_SIZE) ) ++ { ++ break; ++ } ++ len += PAGE_SIZE; ++ next_index++; ++ } ++ ++ if ( len && !done ) ++ { ++ DATA_LIST dllst[2]; ++ ++ dllst[1].page = NULL; ++ dllst[1].offset = rbuf; ++ dllst[1].len = len; ++ dllst[1].rwflag = DLWRITE; ++ ++ if ( !Novfs_Read_Pages((unsigned long)file->private_data, dllst, 2, &len, &offset, session)) ++ { ++ Novfs_copy_cache_pages(mapping, page_lst, len, rbuf, &lru_pvec); ++ page_idx += len >> PAGE_CACHE_SHIFT; ++ if ((int)(len & PAGE_CACHE_MASK) != len) ++ { ++ page_idx++; ++ } ++ } ++ else ++ { ++ done = 1; ++ } ++ } ++ } ++ ++ /* ++ * Free any remaining pages. ++ */ ++ while ( !list_empty(page_lst) ) ++ { ++ struct page *page = list_entry(page_lst->prev, struct page, lru); ++ ++ list_del(&page->lru); ++ page_cache_release(page); ++ } ++ ++ pagevec_lru_add(&lru_pvec); ++ Novfs_Free( rbuf ); ++ } ++ else ++ { ++ retCode = -ENOMEM; ++ } ++ ++ DbgPrint("Novfs_a_readpages: retCode=%d\n", retCode); ++ return (retCode); ++ ++} ++ ++/*++======================================================================*/ ++int Novfs_a_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = 0; ++ loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; ++ size_t len=PAGE_CACHE_SIZE; ++ session_t session=0; ++ DATA_LIST dllst[2]; ++ struct inode *inode = file->f_dentry->d_inode; ++ ++ DbgPrint("Novfs_a_prepare_write: File=0x%x Page=0x%x offset=0x%llx From=%u To=%u filesize=%lld\n", file, page, offset, from, to, i_size_read(file->f_dentry->d_inode)); ++ if (!PageUptodate(page)) ++ { ++ /* ++ * Check to see if whole page ++ */ ++ if((to==PAGE_CACHE_SIZE) && (from == 0)) ++ { ++ SetPageUptodate(page); ++ } ++ ++ /* ++ * Check to see if we can read page. ++ */ ++ else if((file->f_flags & O_ACCMODE) != O_WRONLY) ++ { ++ /* ++ * Get session. ++ */ ++ if (file->f_dentry && file->f_dentry->d_inode) ++ { ++ if (file->f_dentry->d_inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ } ++ } ++ ++ page_cache_get(page); ++ ++ len = i_size_read(inode) - offset; ++ if (len > PAGE_CACHE_SIZE) ++ { ++ len = PAGE_CACHE_SIZE; ++ } ++ ++ if( len ) ++ { ++ /* ++ * Read page from server. ++ */ ++ ++ dllst[1].page = page; ++ dllst[1].offset = 0; ++ dllst[1].len = len; ++ dllst[1].rwflag = DLWRITE; ++ ++ Novfs_Read_Pages((unsigned long)file->private_data, dllst, 2, &len, &offset, session); ++ /* ++ * Zero unnsed page. ++ */ ++ } ++ ++ if (len < PAGE_CACHE_SIZE) ++ { ++ char *adr = kmap_atomic(page, KM_USER0); ++ memset(adr+len, 0, PAGE_CACHE_SIZE-len); ++ kunmap_atomic(adr, KM_USER0); ++ } ++ } ++ else ++ { ++ /* ++ * Zero section of memory that not going to be used. ++ */ ++ char *adr = kmap_atomic(page, KM_USER0); ++ memset(adr, 0, from); ++ memset(adr + to, 0, PAGE_CACHE_SIZE - to); ++ kunmap_atomic(adr, KM_USER0); ++ ++ DbgPrint("Novfs_a_prepare_write: memset 0x%p\n", adr); ++ } ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ } ++ ++// DbgPrint("Novfs_a_prepare_write: return %d\n", retVal); ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Novfs_a_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++ ++{ ++ int retCode = 0; ++ struct inode *inode = page->mapping->host; ++ loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; ++ session_t session=0; ++ PINODE_DATA id; ++ DATA_LIST dlst[1]; ++ size_t len = to - offset; ++ ++ DbgPrint("Novfs_a_commit_write: File=0x%p Page=0x%p offset=0x%x To=%u filesize=%lld\n", file, page, offset, to, i_size_read(file->f_dentry->d_inode)); ++ if (file->f_dentry->d_inode && (id = file->f_dentry->d_inode->u.generic_ip)) ++ { ++ session = Scope_Get_SessionId(id->Scope); ++ if (0 == session) ++ { ++ id->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(id->Scope); ++ } ++ ++ if (pos > inode->i_size) ++ { ++ i_size_write(inode, pos); ++ } ++ ++ if (!PageUptodate(page)) ++ { ++ pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; ++ ++ if (to < offset) ++ { ++ return( retCode ); ++ } ++ dlst[0].page = page; ++ dlst[0].offset = (void *)offset; ++ dlst[0].len = len; ++ dlst[0].rwflag = DLREAD; ++ ++ retCode = Novfs_Write_Pages( id->FileHandle, dlst, 1, len, pos, session); ++ ++ } else { ++ set_page_dirty(page); ++ } ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++ssize_t Novfs_a_direct_IO(int rw, struct kiocb *kiocb, ++ const struct iovec *iov, ++ loff_t offset, ++ unsigned long nr_segs) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: This is a dummy function so that we can allow a file ++ * to get the direct IO flag set. Novfs_f_read and ++ * Novfs_f_write will do the work. Maybe not the best ++ * way to do but it was the easiest to implement. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ return( -EIO ); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *path, *buf; ++ ENTRY_INFO info; ++ unsigned long handle; ++ session_t session; ++ int retCode = -EACCES; ++ ++ ++ DbgPrint("Novfs_i_create: mode=0%o flags=0%o %.*s\n", mode, nd->NDOPENFLAGS, dentry->d_name.len, dentry->d_name.name); ++ ++ if ( IS_ROOT(dentry) || /* Root */ ++ IS_ROOT(dentry->d_parent) || /* User */ ++ IS_ROOT(dentry->d_parent->d_parent) || /* Server */ ++ IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ ++ { ++ return(-EACCES); ++ } ++ ++ if (mode | S_IFREG) ++ { ++ if (dir->u.generic_ip) ++ { ++ session = Scope_Get_SessionId( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)dir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)dir->u.generic_ip)->Scope); ++ } ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ retCode = Novfs_Open_File(path, nd->NDOPENFLAGS|O_RDWR, &info, &handle, session); ++ if ( !retCode && handle ) ++ { ++ Novfs_Close_File(handle, session); ++ if (!Novfs_i_mknod(dir, dentry, mode | S_IFREG, 0)) ++ { ++ if (dentry->d_inode) ++ { ++ ((PINODE_DATA)dentry->d_inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ } ++ } ++ } ++ } ++ Novfs_Free(buf); ++ } ++ } ++ } ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++void update_inode(struct inode *Inode, PENTRY_INFO Info) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ static char dbuf[128]; ++ ++ DbgPrint("update_inode: Inode=0x%x I_ino=%d\n", Inode, Inode->i_ino); ++ ++ DbgPrint("update_inode: atime=%s\n", ctime_r(&Info->atime.tv_sec, dbuf)); ++ DbgPrint("update_inode: ctime=%s\n", ctime_r(&Info->ctime.tv_sec, dbuf)); ++ DbgPrint("update_inode: mtime=%s %d\n", ctime_r(&Info->mtime.tv_sec, dbuf), Info->mtime.tv_nsec); ++ DbgPrint("update_inode: size=%lld\n", Info->size); ++ DbgPrint("update_inode: mode=0%o\n", Info->mode); ++ ++ if ( Inode && ++ ( (Inode->i_size != Info->size) || ++ (Inode->i_mtime.tv_sec != Info->mtime.tv_sec) || ++ (Inode->i_mtime.tv_nsec != Info->mtime.tv_nsec) )) ++ { ++ DbgPrint("update_inode: calling invalidate_remote_inode sz %d %d\n", Inode->i_size, Info->size); ++ DbgPrint("update_inode: calling invalidate_remote_inode sec %d %d\n", Inode->i_mtime.tv_sec, Info->mtime.tv_sec); ++ DbgPrint("update_inode: calling invalidate_remote_inode ns %d %d\n", Inode->i_mtime.tv_nsec, Info->mtime.tv_nsec); ++ invalidate_remote_inode( Inode ); ++ } ++ ++ Inode->i_mode = Info->mode; ++ Inode->i_size = Info->size; ++ Inode->i_atime = Info->atime; ++ Inode->i_ctime = Info->ctime; ++ Inode->i_mtime = Info->mtime; ++ ++ if (Inode->i_size && Inode->i_blksize) ++ { ++ Inode->i_blocks = (u_long)(Info->size >> (loff_t)Inode->i_blkbits); ++ Inode->i_bytes = Info->size & (Inode->i_blksize - 1); ++ ++ DbgPrint("update_inode: i_blksize=%d\n", Inode->i_blksize); ++ DbgPrint("update_inode: i_blkbits=%d\n", Inode->i_blkbits); ++ DbgPrint("update_inode: i_blocks=%d\n", Inode->i_blocks); ++ DbgPrint("update_inode: i_bytes=%d\n", Inode->i_bytes); ++ } ++} ++ ++/*++======================================================================*/ ++struct dentry * Novfs_i_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct dentry *retVal = ERR_PTR(-ENOENT); ++ struct dentry *parent; ++ PENTRY_INFO info=NULL; ++ PINODE_DATA id; ++ struct inode *inode=NULL; ++ uid_t uid=current->euid; ++ ino_t ino=0; ++ struct qstr name; ++ ++ DbgPrint("Novfs_i_lookup: dir 0x%x %d name %.*s hash %d inode 0x%0p\n", dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name, dentry->d_name.hash, dentry->d_inode); ++ ++ if (dir && (id = dir->u.generic_ip) ) ++ { ++ retVal = 0; ++ if ( IS_ROOT( dentry )) ++ { ++ DbgPrint("Novfs_i_lookup: Root entry=0x%x\n", Novfs_root); ++ inode = Novfs_root->d_inode; ++ return(0); ++ } ++ else ++ { ++ info = Novfs_Malloc(sizeof(ENTRY_INFO)+PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (info) ++ { ++ if ( NULL == (retVal = ERR_PTR(verify_dentry( dentry, 1 )))) ++ { ++ name.name = dentry->d_name.name; ++ name.len = dentry->d_name.len; ++ name.hash = Novfs_internal_hash(&name); ++ ++ if (Novfs_lock_inode_cache( dir )) ++ { ++ if ( !Novfs_get_entry(dir, &name, &ino, info) ) ++ { ++ inode = ilookup(dentry->d_sb, ino); ++ if ( inode ) ++ { ++ update_inode(inode, info); ++ } ++ } ++ Novfs_unlock_inode_cache( dir ); ++ } ++ ++ if ( !inode && ino ) ++ { ++ uid = Scope_Get_Uid( id->Scope ); ++ if (Novfs_lock_inode_cache( dir )) ++ { ++ inode = Novfs_get_inode(dentry->d_sb, info->mode, 0, uid, ino, &name); ++ if ( inode ) ++ { ++ if ( !Novfs_get_entry(dir, &dentry->d_name, &ino, info) ) ++ { ++ update_inode(inode, info); ++ } ++ } ++ Novfs_unlock_inode_cache( dir ); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ if ( !retVal ) ++ { ++ dentry->d_op = &Novfs_dentry_operations; ++ if (inode) ++ { ++ parent = dget_parent(dentry); ++ Novfs_d_add(dentry->d_parent, dentry, inode, 1); ++ dput(parent); ++ } ++ else ++ { ++ d_add( dentry, inode); ++ } ++ } ++ ++ if (info) Novfs_Free(info); ++ ++ DbgPrint("Novfs_i_lookup: inode=0x%x dentry->d_inode=0x%x return=0x%x\n", dir, dentry->d_inode, retVal); ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_unlink(struct inode *dir, struct dentry *dentry) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOENT; ++ struct inode *inode; ++ session_t session; ++ char *path, *buf; ++ uint64_t t64; ++ ++ DbgPrint("Novfs_i_unlink: dir=0x%x dir->i_ino=%d %.*s\n", dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name); ++ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry)=%d\n", IS_ROOT(dentry)); ++ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent)=%d\n", IS_ROOT(dentry->d_parent)); ++ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent->d_parent)=%d\n", IS_ROOT(dentry->d_parent->d_parent)); ++ DbgPrint("Novfs_i_unlink: IS_ROOT(dentry->d_parent->d_parent->d_parent)=%d\n", IS_ROOT(dentry->d_parent->d_parent->d_parent) ); ++ ++ if ( IS_ROOT(dentry) || /* Root */ ++ IS_ROOT(dentry->d_parent) || /* User */ ++ (!IS_ROOT(dentry->d_parent->d_parent) && /* Server */ ++ IS_ROOT(dentry->d_parent->d_parent->d_parent)) ) /* Volume */ ++ { ++ return(-EACCES); ++ } ++ ++ inode = dentry->d_inode; ++ if ( inode ) ++ { ++ DbgPrint("Novfs_i_unlink: dir=0x%x dir->i_ino=%d inode=0x%x ino=%d\n", dir, dir->i_ino, inode, inode->i_ino); ++ if (inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ DbgPrint("Novfs_i_unlink: path %s mode 0%o\n", path, inode->i_mode); ++ if (IS_ROOT(dentry->d_parent->d_parent)) ++ { ++ retCode = do_logout(&dentry->d_name); ++ } ++ else ++ { ++ retCode = Novfs_Delete(path, S_ISDIR(inode->i_mode), session); ++ } ++ if ( !retCode || IS_DEADDIR(inode)) ++ { ++ Novfs_remove_inode_entry(dir, &dentry->d_name, 0); ++ dentry->d_time = 0; ++ t64 = 0; ++ Scope_Set_UserSpace(&t64, &t64, &t64, &t64); ++ retCode = 0; ++ } ++ } ++ Novfs_Free(buf); ++ } ++ } ++ } ++ ++ DbgPrint("Novfs_i_unlink: retCode 0x%x\n", retCode); ++ return (retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *path, *buf; ++ session_t session; ++ int retCode=0; ++ struct inode *inode; ++ ENTRY_INFO info; ++ uid_t uid; ++ ++ DbgPrint("Novfs_i_mkdir: dir=0x%p ino=%d dentry=0x%p %.*s mode=0%o\n", dir, dir->i_ino, dentry, dentry->d_name.len, dentry->d_name.name, mode); ++ ++ if ( IS_ROOT(dentry) || /* Root */ ++ IS_ROOT(dentry->d_parent) || /* User */ ++ IS_ROOT(dentry->d_parent->d_parent) || /* Server */ ++ IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ ++ { ++ return(-EACCES); ++ } ++ ++ mode |= S_IFDIR; ++ mode &= (S_IFMT | S_IRWXU); ++ if ( dir->u.generic_ip ) ++ { ++ session = Scope_Get_SessionId( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)dir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)dir->u.generic_ip)->Scope); ++ } ++ ++ uid = Scope_Get_Uid( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ DbgPrint("Novfs_i_mkdir: path %s\n", path); ++ retCode = Novfs_Create(path, S_ISDIR(mode), session); ++ if ( !retCode ) ++ { ++ retCode = Novfs_Get_File_Info(path, &info, session ); ++ if ( !retCode ) ++ { ++ retCode = Novfs_i_mknod(dir, dentry, mode, 0); ++ inode = dentry->d_inode; ++ if (inode) ++ { ++ update_inode(inode, &info); ++ ((PINODE_DATA)inode->u.generic_ip)->Flags &= ~UPDATE_INODE; ++ ++ dentry->d_time = jiffies+(File_update_timeout*HZ); ++ ++ Novfs_lock_inode_cache(dir); ++ if (Novfs_update_entry( dir, &dentry->d_name, 0, &info )) ++ { ++ Novfs_add_inode_entry(dir, &dentry->d_name, inode->i_ino, &info); ++ } ++ Novfs_unlock_inode_cache(dir); ++ } ++ ++ } ++ } ++ } ++ Novfs_Free(buf); ++ } ++ } ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_rmdir(struct inode *inode, struct dentry *dentry) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ return(Novfs_i_unlink(inode, dentry)); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct inode *inode=NULL; ++ int retCode = -EACCES; ++ uid_t uid; ++ struct dentry *parent; ++ ++ if ( IS_ROOT(dentry) || /* Root */ ++ IS_ROOT(dentry->d_parent) || /* User */ ++ IS_ROOT(dentry->d_parent->d_parent) || /* Server */ ++ IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ ++ { ++ return(-EACCES); ++ } ++ ++ if ( ((PINODE_DATA)dir->u.generic_ip) ) ++ { ++ uid = Scope_Get_Uid( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ if (mode & (S_IFREG | S_IFDIR)) ++ { ++ inode = Novfs_get_inode(dir->i_sb, mode, dev, uid, 0, &dentry->d_name); ++ } ++ } ++ ++ if (inode) ++ { ++ ENTRY_INFO info; ++ ++ dentry->d_op = &Novfs_dentry_operations; ++ parent = dget_parent(dentry); ++ Novfs_d_add(parent, dentry, inode, 0); ++ memset(&info, 0, sizeof(info)); ++ info.mode = inode->i_mode; ++ Novfs_lock_inode_cache( dir ); ++ Novfs_add_inode_entry( dir, &dentry->d_name, inode->i_ino, &info); ++ Novfs_unlock_inode_cache( dir ); ++ ++ dput(parent); ++ ++ retCode = 0; ++ } ++ DbgPrint("Novfs_i_mknod: return 0x%x\n", retCode); ++ return retCode; ++} ++ ++/*++======================================================================*/ ++int Novfs_i_rename(struct inode *odir, struct dentry *od, struct inode *ndir, struct dentry *nd) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = -ENOTEMPTY; ++ char *newpath, *newbuf, *newcon; ++ char *oldpath, *oldbuf, *oldcon; ++ struct qstr newname, oldname; ++ PENTRY_INFO info=NULL; ++ int oldlen, newlen; ++ session_t session; ++ ino_t ino; ++ ++ ++ if ( IS_ROOT(od) || /* Root */ ++ IS_ROOT(od->d_parent) || /* User */ ++ IS_ROOT(od->d_parent->d_parent) || /* Server */ ++ IS_ROOT(od->d_parent->d_parent->d_parent) ) /* Volume */ ++ { ++ return(-EACCES); ++ } ++ ++ DbgPrint("Novfs_i_rename: odir=0x%p ino=%d ndir=0x%p ino=%d\n", odir, odir->i_ino, ndir, ndir->i_ino); ++ ++ oldbuf = Novfs_Malloc(PATH_LENGTH_BUFFER*2, GFP_KERNEL); ++ newbuf = oldbuf+PATH_LENGTH_BUFFER; ++ if ( oldbuf && newbuf ) ++ { ++ oldpath = Novfs_dget_path(od, oldbuf, PATH_LENGTH_BUFFER); ++ newpath = Novfs_dget_path(nd, newbuf, PATH_LENGTH_BUFFER); ++ if (oldpath && newpath) ++ { ++ oldlen = PATH_LENGTH_BUFFER-(int)(oldpath-oldbuf); ++ newlen = PATH_LENGTH_BUFFER-(int)(newpath-newbuf); ++ ++ DbgPrint("Novfs_i_rename: odir=0x%x od->inode=0x%x\n", odir, od->d_inode); ++ DbgPrint("Novfs_i_rename: old path %s\n", oldpath); ++ DbgPrint("Novfs_i_rename: new path %s\n", newpath); ++ ++ /* ++ * Check to see if two different servers or different volumes ++ */ ++ newcon = strchr(newpath+1, '\\'); ++ oldcon = strchr(oldpath+1, '\\'); ++ DbgPrint("Novfs_i_rename: newcon=0x%x newpath=0x%x\n", newcon, newpath); ++ DbgPrint("Novfs_i_rename: oldcon=0x%x oldpath=0x%x\n", oldcon, oldpath); ++ retCode = -EXDEV; ++ if ( newcon && oldcon && ((int)(newcon-newpath) == (int)(oldcon-oldpath)) ) ++ { ++ newcon = strchr(newcon+1, '\\'); ++ oldcon = strchr(oldcon+1, '\\'); ++ DbgPrint("Novfs_i_rename2: newcon=0x%x newpath=0x%x\n", newcon, newpath); ++ DbgPrint("Novfs_i_rename2: oldcon=0x%x oldpath=0x%x\n", oldcon, oldpath); ++ if ( newcon && oldcon && ((int)(newcon-newpath) == (int)(oldcon-oldpath)) ) ++ { ++ newname.name = newpath; ++ newname.len = (int)(newcon-newpath); ++ newname.hash = 0; ++ ++ oldname.name = oldpath; ++ oldname.len = (int)(oldcon-oldpath); ++ oldname.hash = 0; ++ if ( !Novfs_d_strcmp(&newname, &oldname)) ++ { ++ ++ if ( od->d_inode && od->d_inode->u.generic_ip ) ++ { ++ ++ if (nd->d_inode && nd->d_inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)ndir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( nd ); ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ } ++ ++ retCode = Novfs_Delete(newpath, S_ISDIR(nd->d_inode->i_mode), session); ++ } ++ ++ ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)ndir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( nd ); ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ } ++ retCode = Novfs_Rename_File( ++ S_ISDIR(od->d_inode->i_mode), ++ oldpath, ++ oldlen-1, ++ newpath, ++ newlen-1, ++ session); ++ ++ if ( !retCode ) ++ { ++ info = (PENTRY_INFO)oldbuf; ++ od->d_time = 0; ++ Novfs_remove_inode_entry(odir, &od->d_name, 0); ++ Novfs_Get_File_Info(newpath, info, session); ++ nd->d_time = jiffies+(File_update_timeout*HZ); ++ if (Novfs_update_entry(ndir, &nd->d_name, 0, info)) ++ { ++ if (nd->d_inode && nd->d_inode->i_ino) ++ { ++ ino = nd->d_inode->i_ino; ++ } ++ else ++ { ++ ino = (ino_t)InterlockedIncrement(&Novfs_Inode_Number); ++ } ++ Novfs_add_inode_entry(ndir, &nd->d_name, ino, info); ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ if (oldbuf) Novfs_Free(oldbuf); ++ ++ return( retCode ); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_permission(struct inode *inode, int mask) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode=0; ++ ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_setattr(struct dentry *dentry, struct iattr *attr) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *path, *buf; ++ struct inode *inode=dentry->d_inode; ++ char atime_buf[32]; ++ char mtime_buf[32]; ++ char ctime_buf[32]; ++ unsigned int ia_valid = attr->ia_valid; ++ session_t session; ++ int retVal = 0; ++ ++ if ( IS_ROOT(dentry) || /* Root */ ++ IS_ROOT(dentry->d_parent) || /* User */ ++ IS_ROOT(dentry->d_parent->d_parent) || /* Server */ ++ IS_ROOT(dentry->d_parent->d_parent->d_parent) ) /* Volume */ ++ { ++ return(-EACCES); ++ } ++ ++ if (inode && inode->u.generic_ip) ++ { ++ session = Scope_Get_SessionId( ((PINODE_DATA)inode->u.generic_ip)->Scope); ++ if (0 == session) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ } ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ strcpy(atime_buf, "Unspecified"); ++ strcpy(mtime_buf, "Unspecified"); ++ strcpy(ctime_buf, "Unspecified"); ++ if (attr->ia_valid & ATTR_ATIME) ++ { ++ ctime_r(&attr->ia_atime.tv_sec, atime_buf); ++ } ++ if (attr->ia_valid & ATTR_MTIME) ++ { ++ ctime_r(&attr->ia_mtime.tv_sec, mtime_buf); ++ } ++ if (attr->ia_valid & ATTR_CTIME) ++ { ++ ctime_r(&attr->ia_ctime.tv_sec, ctime_buf); ++ } ++ /* Removed for Bug 132374. jlt ++ DbgPrint("Novfs_i_setattr: %s\n" \ ++ " ia_valid: 0x%x\n" \ ++ " ia_mode: 0%o\n" \ ++ " ia_uid: %d\n" \ ++ " ia_gid: %d\n" \ ++ " ia_size: %lld\n" \ ++ " ia_atime: %s\n" \ ++ " ia_mtime: %s\n" \ ++ " ia_ctime: %s\n" \ ++ " ia_attr_flags: 0x%x\n", ++ path, ++ attr->ia_valid, ++ attr->ia_mode, ++ attr->ia_uid, ++ attr->ia_gid, ++ attr->ia_size, ++ atime_buf, ++ mtime_buf, ++ ctime_buf, ++ attr->ia_attr_flags); ++ */ ++ ++ if ( !(retVal = Novfs_Set_Attr(path, attr, session) ) ) ++ { ++ ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ ++ if (ia_valid & ATTR_ATIME) ++ inode->i_atime = attr->ia_atime; ++ if (ia_valid & ATTR_MTIME) ++ inode->i_mtime = attr->ia_mtime; ++ if (ia_valid & ATTR_CTIME) ++ inode->i_ctime = attr->ia_ctime; ++ if (ia_valid & ATTR_MODE) { ++ inode->i_mode = attr->ia_mode & (S_IFMT | S_IRWXU); ++ } ++ } ++ } ++ } ++ Novfs_Free(buf); ++ } ++ ++ return(retVal); ++} ++ ++/*++======================================================================*/ ++int Novfs_i_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode = 0; ++ char atime_buf[32]; ++ char mtime_buf[32]; ++ char ctime_buf[32]; ++ struct inode *inode = dentry->d_inode; ++ ++ ENTRY_INFO info; ++ char *path, *buf; ++ session_t session; ++ PINODE_DATA id; ++ ++ if ( !IS_ROOT(dentry) && ++ !IS_ROOT(dentry->d_parent) ) ++ { ++ session = 0; ++ id = dentry->d_inode->u.generic_ip; ++ ++ if (id && (id->Flags & UPDATE_INODE) ) ++ { ++ session = Scope_Get_SessionId( id->Scope ); ++ ++ if (0 == session) ++ { ++ id->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(id->Scope); ++ } ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Novfs_dget_path(dentry, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ retCode = Novfs_Get_File_Info(path, &info, session ); ++ if ( !retCode ) ++ { ++ update_inode(inode, &info); ++ id->Flags &= ~UPDATE_INODE; ++ } ++ } ++ Novfs_Free(buf); ++ } ++ } ++ } ++ ++ kstat->ino = inode->i_ino; ++ kstat->dev = inode->i_sb->s_dev; ++ kstat->mode = inode->i_mode; ++ kstat->nlink = inode->i_nlink; ++ kstat->uid = inode->i_uid; ++ kstat->gid = inode->i_gid; ++ kstat->rdev = inode->i_rdev; ++ kstat->size = i_size_read(inode); ++ kstat->atime = inode->i_atime; ++ kstat->mtime = inode->i_mtime; ++ kstat->ctime = inode->i_ctime; ++ kstat->blksize = inode->i_blksize; ++ kstat->blocks = inode->i_blocks; ++ if (inode->i_bytes) ++ { ++ kstat->blocks++; ++ } ++ ctime_r(&kstat->atime.tv_sec, atime_buf); ++ ctime_r(&kstat->mtime.tv_sec, mtime_buf); ++ ctime_r(&kstat->ctime.tv_sec, ctime_buf); ++ ++ ++ DbgPrint("Novfs_i_getattr: 0x%x <%.*s>\n" \ ++ " ino: %d\n" \ ++ " dev: 0x%x\n" \ ++ " mode: 0%o\n" \ ++ " nlink: 0x%x\n" \ ++ " uid: 0x%x\n" \ ++ " gid: 0x%x\n" \ ++ " rdev: 0x%x\n" \ ++ " size: 0x%llx\n" \ ++ " atime: %s\n" \ ++ " mtime: %s\n" \ ++ " ctime: %s\n" \ ++ " blksize: 0x%x\n" \ ++ " blocks: 0x%x\n", ++ retCode, dentry->d_name.len, dentry->d_name.name, ++ kstat->ino, ++ kstat->dev, ++ kstat->mode, ++ kstat->nlink, ++ kstat->uid, ++ kstat->gid, ++ kstat->rdev, ++ kstat->size, ++ atime_buf, ++ mtime_buf, ++ ctime_buf, ++ kstat->blksize, ++ kstat->blocks); ++ return( retCode ); ++} ++ ++ ++/*++======================================================================*/ ++int Novfs_i_revalidate(struct dentry *dentry) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ++ DbgPrint("Novfs_i_revalidate: name %.*s\n", dentry->d_name.len, dentry->d_name.name); ++ ++ return(0); ++} ++ ++/*++======================================================================*/ ++void Novfs_read_inode(struct inode *inode) ++/* ++ * Arguments: ++ * ++ * Returns: nothing ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: Superblock operation ++ * ++ *=======================================================================-*/ ++{ ++ DbgPrint( "Novfs_read_inode: 0x%x %d\n", inode, inode->i_ino); ++} ++ ++/*++======================================================================*/ ++void Novfs_write_inode(struct inode *inode) ++/* ++ * Arguments: ++ * ++ * Returns: nothing ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: Superblock operation ++ * ++ *=======================================================================-*/ ++{ ++ DbgPrint( "Novfs_write_inode: Inode=0x%x Ino=%d\n", inode, inode->i_ino); ++} ++ ++/*++======================================================================*/ ++int Novfs_notify_change(struct dentry *dentry, struct iattr *attr) ++/* ++ * Arguments: ++ * ++ * Returns: error code ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: Superblock operation ++ * ++ *=======================================================================-*/ ++{ ++ struct inode *inode = dentry->d_inode; ++ ++ DbgPrint( "Novfs_notify_change: Dentry=0x%x Name=%.*s Inode=0x%x Ino=%d ia_valid=0x%x\n", ++ dentry, dentry->d_name.len, dentry->d_name.name,inode, inode->i_ino, attr->ia_valid); ++ return(0); ++} ++ ++/*++======================================================================*/ ++void Novfs_clear_inode(struct inode *inode) ++/* ++ * Arguments: sb - pointer to the super_block ++ * buf - pointer to the statfs buffer ++ * ++ * Returns: 0 ++ * ++ * Abstract: Called when statfs(2) system called. ++ * ++ * Notes: ++ * ++ * Environment: Superblock operation ++ * ++ *========================================================================*/ ++{ ++ InodeCount--; ++ ++ if ( inode->u.generic_ip ) ++ { ++ PINODE_DATA id=inode->u.generic_ip; ++ ++ DbgPrint("Novfs_clear_inode: inode=0x%x ino=%d Scope=0x%p Name=%s\n", inode, inode->i_ino, id->Scope, id->Name); ++ ++ Novfs_free_inode_cache(inode); ++ ++ down( &InodeList_lock ); ++ list_del( &id->IList ); ++ up( &InodeList_lock ); ++ ++ ++ Novfs_Free(inode->u.generic_ip); ++ inode->u.generic_ip = NULL; ++ ++ remove_inode_hash( inode ); ++ ++ } ++ else ++ { ++ DbgPrint("Novfs_clear_inode: inode=0x%x ino=%d\n", inode, inode->i_ino); ++ } ++} ++ ++/*++======================================================================*/ ++int ++NO_TRACE ++Novfs_show_options( struct seq_file *s, struct vfsmount *m ) ++/* ++ * Arguments: ++ * ++ * Returns: 0 ++ * ++ * Abstract: Called when /proc/mounts is read ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *buf, *path, *tmp; ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = d_path(m->mnt_root, m, buf, PATH_LENGTH_BUFFER); ++ if (path) ++ { ++ if ( !Novfs_CurrentMount || (Novfs_CurrentMount && strcmp(Novfs_CurrentMount, path))) ++ { ++ DbgPrint("Novfs_show_options: %.*s %.*s %s\n", m->mnt_root->d_name.len, m->mnt_root->d_name.name, ++ m->mnt_mountpoint->d_name.len, m->mnt_mountpoint->d_name.name, path); ++ tmp = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER - (int)(path-buf), GFP_KERNEL); ++ if (tmp) ++ { ++ strcpy(tmp, path); ++ path = Novfs_CurrentMount; ++ Novfs_CurrentMount = tmp; ++ Daemon_SetMountPoint( Novfs_CurrentMount ); ++ ++ if (path) ++ { ++ Novfs_Free(path); ++ } ++ } ++ } ++ } ++ Novfs_Free( buf ); ++ } ++ return(0); ++} ++ ++/*++======================================================================*/ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++int Novfs_statfs(struct dentry *de, struct kstatfs *buf) ++#else ++int Novfs_statfs(struct super_block *sb, struct kstatfs *buf) ++#endif ++/* ++ * Arguments: sb - pointer to the super_block ++ * buf - pointer to the statfs buffer ++ * ++ * Returns: 0 ++ * ++ * Abstract: Called when statfs(2) system called. ++ * ++ * Notes: ++ * ++ * Environment: Superblock operation ++ * ++ *========================================================================*/ ++{ ++ uint64_t td, fd, te, fe; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ struct super_block *sb = de->d_sb; ++#endif ++ ++ UNUSED_VARIABLE(sb); ++ ++ DbgPrint("Novfs_statfs:\n"); ++ ++ td = fd = te = fe = 0; ++ ++ Scope_Get_UserSpace( &td, &fd, &te, &fe ); ++ ++ DbgPrint("td=%llu\n", td); ++ DbgPrint("fd=%llu\n", fd); ++ DbgPrint("te=%llu\n", te); ++ DbgPrint("fe=%llu\n", fd); ++ ++ buf->f_type = sb->s_magic; ++ buf->f_bsize = sb->s_blocksize; ++ buf->f_namelen = NW_MAX_PATH_LENGTH; ++ buf->f_blocks = (sector_t)(td + (uint64_t)(sb->s_blocksize-1)) >> (uint64_t)sb->s_blocksize_bits; ++ buf->f_bfree = (sector_t)fd >> (uint64_t)sb->s_blocksize_bits; ++ buf->f_bavail = (sector_t)buf->f_bfree; ++ buf->f_files = (sector_t)te; ++ buf->f_ffree = (sector_t)fe; ++ buf->f_frsize = sb->s_blocksize; ++ if (te > 0xffffffff) ++ buf->f_files = 0xffffffff; ++ ++ if (fe > 0xffffffff) ++ buf->f_ffree = 0xffffffff; ++ ++ ++ DbgPrint("f_type: 0x%x\n", buf->f_type); ++ DbgPrint("f_bsize: %u\n", buf->f_bsize); ++ DbgPrint("f_namelen: %d\n", buf->f_namelen); ++ DbgPrint("f_blocks: %llu\n", buf->f_blocks); ++ DbgPrint("f_bfree: %llu\n", buf->f_bfree); ++ DbgPrint("f_bavail: %llu\n", buf->f_bavail); ++ DbgPrint("f_files: %llu\n", buf->f_files); ++ DbgPrint("f_ffree: %llu\n", buf->f_ffree); ++ DbgPrint("f_frsize: %u\n", buf->f_frsize); ++ ++ return 0; ++} ++ ++/*++======================================================================*/ ++struct inode *Novfs_get_inode(struct super_block *sb, int mode, int dev, uid_t Uid, ino_t ino, struct qstr *name) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *=======================================================================-*/ ++{ ++ struct inode * inode = new_inode(sb); ++ ++ if (inode) ++ { ++ InodeCount++; ++ inode->i_mode = mode; ++ inode->i_uid = Uid; ++ inode->i_gid = 0; ++ inode->i_blksize = sb->s_blocksize; ++ inode->i_blkbits = sb->s_blocksize_bits; ++ inode->i_blocks = 0; ++ inode->i_rdev = 0; ++ inode->i_ino = (ino) ? ino: (ino_t)InterlockedIncrement(&Novfs_Inode_Number); ++ inode->i_mapping->a_ops = &Novfs_aops; ++ inode->i_atime.tv_sec = 0; ++ inode->i_atime.tv_nsec = 0; ++ inode->i_mtime = inode->i_ctime = inode->i_atime; ++ ++ DbgPrint("Novfs_get_inode: Inode=0x%p I_ino=%d len=%d\n", inode, inode->i_ino, name->len); ++ ++ if (NULL != (inode->u.generic_ip = Novfs_Malloc(sizeof(INODE_DATA)+name->len, GFP_KERNEL))) ++ { ++ PINODE_DATA id; ++ id = inode->u.generic_ip; ++ ++ DbgPrint("Novfs_get_inode: u.generic_ip 0x%p\n", id); ++ ++ id->Scope = NULL; ++ id->Flags = 0; ++ id->Inode = inode; ++ INIT_LIST_HEAD( &id->DirCache ); ++ init_MUTEX( &id->DirCacheLock ); ++ ++ id->FileHandle = 0; ++ id->CacheFlag = 0; ++ ++ down( &InodeList_lock ); ++ ++ list_add_tail(&id->IList, &InodeList); ++ up( &InodeList_lock ); ++ ++ id->Name[0] = '\0'; ++ ++ memcpy(id->Name, name->name, name->len); ++ id->Name[name->len] = '\0'; ++ ++ DbgPrint("Novfs_get_inode: name %s\n", id->Name); ++ } ++ ++ insert_inode_hash(inode); ++ ++ switch (mode & S_IFMT) { ++ ++ case S_IFREG: ++ inode->i_op = &Novfs_file_inode_operations; ++ inode->i_fop = &Novfs_file_operations; ++ break; ++ ++ case S_IFDIR: ++ inode->i_op = &Novfs_inode_operations; ++ inode->i_fop = &Novfs_dir_operations; ++ inode->i_blksize = 0; ++ inode->i_blkbits = 0; ++ break; ++ ++ default: ++ init_special_inode(inode, mode, dev); ++ break; ++ } ++ ++ DbgPrint("Novfs_get_inode: size=%lld\n", inode->i_size); ++ DbgPrint("Novfs_get_inode: mode=0%o\n", inode->i_mode); ++ DbgPrint("Novfs_get_inode: i_blksize=%d\n", inode->i_blksize); ++ DbgPrint("Novfs_get_inode: i_blkbits=%d\n", inode->i_blkbits); ++ DbgPrint("Novfs_get_inode: i_blocks=%d\n", inode->i_blocks); ++ DbgPrint("Novfs_get_inode: i_bytes=%d\n", inode->i_bytes); ++ } ++ ++ DbgPrint("Novfs_get_inode: 0x%p %d\n", inode, inode->i_ino); ++ return (inode); ++} ++ ++/*++======================================================================*/ ++int Novfs_fill_super (struct super_block *SB, void *Data, int Silent) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct inode * inode; ++ struct dentry *server, *tree; ++ struct qstr name; ++/* PINODE_DATA id; ++*/ ++ ENTRY_INFO info; ++ ++ UNUSED_VARIABLE(Data); ++ UNUSED_VARIABLE(Silent); ++ ++ SB->s_blocksize = PAGE_CACHE_SIZE; ++ SB->s_blocksize_bits = PAGE_CACHE_SHIFT; ++ SB->s_maxbytes = 0xFFFFFFFFFFFFFFFFULL; /* Max file size */ ++ SB->s_op = &Novfs_ops; ++ SB->s_flags |= (MS_NODIRATIME | MS_NODEV | MS_POSIXACL); ++ SB->s_magic = NOVFS_MAGIC; ++ ++ ++ name.len = 1; ++ name.name = "/"; ++ ++ inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name); ++ if (!inode) ++ { ++ return( -ENOMEM ); ++ } ++ ++ Novfs_root = d_alloc_root(inode); ++ ++ if (!Novfs_root) ++ { ++ iput(inode); ++ return( -ENOMEM ); ++ } ++ Novfs_root->d_time = jiffies+(File_update_timeout*HZ); ++ ++ inode->i_atime = ++ inode->i_ctime = ++ inode->i_mtime = CURRENT_TIME; ++ ++ ++ SB->s_root = Novfs_root; ++ ++ DbgPrint( "Novfs_fill_super: root 0x%x\n", Novfs_root); ++ ++ if (Novfs_root) ++ { ++ Novfs_root->d_op = &Novfs_dentry_operations; ++ ++ name.name = SERVER_DIRECTORY_NAME; ++ name.len = strlen(SERVER_DIRECTORY_NAME); ++ name.hash = Novfs_internal_hash( &name ); ++ ++ inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name); ++ if (inode) ++ { ++ info.mode = inode->i_mode; ++ info.namelength = 0; ++ inode->i_size = info.size = 0; ++ inode->i_uid = info.uid = 0; ++ inode->i_gid = info.gid = 0; ++ inode->i_atime = info.atime = ++ inode->i_ctime = info.ctime = ++ inode->i_mtime = info.mtime = CURRENT_TIME; ++ ++ server = d_alloc(Novfs_root, &name); ++ if (server) ++ { ++ server->d_op = &Novfs_dentry_operations; ++ server->d_time = 0xffffffff; ++ d_add(server, inode); ++ DbgPrint( "Novfs_fill_super: d_add %s 0x%x\n", SERVER_DIRECTORY_NAME, server); ++ Novfs_add_inode_entry(Novfs_root->d_inode, &name, inode->i_ino, &info); ++ } ++ } ++ ++ name.name = TREE_DIRECTORY_NAME; ++ name.len = strlen(TREE_DIRECTORY_NAME); ++ name.hash = Novfs_internal_hash( &name ); ++ ++ inode = Novfs_get_inode(SB, S_IFDIR | 0777, 0, 0, 0, &name); ++ if (inode) ++ { ++ info.mode = inode->i_mode; ++ info.namelength = 0; ++ inode->i_size = info.size = 0; ++ inode->i_uid = info.uid = 0; ++ inode->i_gid = info.gid = 0; ++ inode->i_atime = info.atime = ++ inode->i_ctime = info.ctime = ++ inode->i_mtime = info.mtime = CURRENT_TIME; ++ tree = d_alloc(Novfs_root, &name); ++ if (tree) ++ { ++ tree->d_op = &Novfs_dentry_operations; ++ tree->d_time = 0xffffffff; ++ ++ d_add(tree, inode); ++ DbgPrint( "Novfs_fill_super: d_add %s 0x%x\n", TREE_DIRECTORY_NAME, tree); ++ Novfs_add_inode_entry(Novfs_root->d_inode, &name, inode->i_ino, &info); ++ } ++ } ++ } ++ ++ return( 0 ); ++} ++ ++/*++======================================================================*/ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++int Novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data, struct vfsmount *Mnt) ++#else ++struct super_block * Novfs_get_sb(struct file_system_type *Fstype, int Flags, const char *Dev_name, void *Data) ++#endif ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ int sb; ++#else ++ struct super_block *sb; ++#endif ++ ++ UNUSED_VARIABLE(Dev_name); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ sb = get_sb_nodev(Fstype, Flags, Data, Novfs_fill_super, Mnt); ++#else ++ sb = get_sb_nodev(Fstype, Flags, Data, Novfs_fill_super); ++#endif ++ ++ DbgPrint( "Novfs_get_sb: sb=0x%x Fstype=0x%x Dev_name=%s\n", sb, Fstype, Dev_name); ++ ++ return (sb ); ++} ++ ++/*++======================================================================*/ ++void Novfs_kill_sb(struct super_block *SB) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ kill_litter_super(SB); ++} ++ ++/*++======================================================================*/ ++ssize_t Novfs_Control_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ssize_t retval=0; ++ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(buf); ++ UNUSED_VARIABLE(nbytes); ++ UNUSED_VARIABLE(ppos); ++ ++ DbgPrint( "Novfs_Control_read: kernel_locked 0x%x\n", kernel_locked()); ++ ++ return retval; ++} ++ ++/*++======================================================================*/ ++ssize_t Novfs_Control_write(struct file * file, const char * buf, size_t nbytes, loff_t *ppos) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ssize_t retval=0; ++ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(buf); ++ UNUSED_VARIABLE(nbytes); ++ UNUSED_VARIABLE(ppos); ++ ++ DbgPrint( "Novfs_Control_write: kernel_locked 0x%x\n", kernel_locked()); ++ if (buf && nbytes) ++ { ++ } ++ ++ return(retval); ++} ++ ++/*++======================================================================*/ ++int Novfs_Control_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retval=0; ++ ++ UNUSED_VARIABLE(inode); ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(cmd); ++ UNUSED_VARIABLE(arg); ++ ++ DbgPrint( "Novfs_Control_ioctl: kernel_locked 0x%x\n", kernel_locked()); ++ ++ return(retval); ++} ++ ++/*++======================================================================*/ ++int __init init_novfs (void) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode; ++ ++ ++ retCode = Init_Procfs_Interface(); ++ ++ init_profile(); ++ ++ if ( !retCode ) ++ { ++ DbgPrint("init_novfs: %s %s %s\n", __DATE__, __TIME__, NOVFS_VERSION_STRING); ++ Init_Daemon_Queue(); ++ Scope_Init(); ++ retCode = register_filesystem(&Novfs_fs_type); ++ if ( retCode ) ++ { ++ Uninit_Procfs_Interface(); ++ Uninit_Daemon_Queue(); ++ Scope_Uninit(); ++ } ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++void __exit exit_novfs(void) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ printk( KERN_INFO "exit_novfs\n"); ++ ++ Scope_Uninit(); ++ printk( KERN_INFO "exit_novfs after Scope_Uninit\n"); ++ ++ Uninit_Daemon_Queue(); ++ printk( KERN_INFO "exit_novfs after Uninit_Daemon_Queue\n"); ++ ++ uninit_profile(); ++ printk( KERN_INFO "exit_novfs after uninit_profile\n"); ++ ++ Uninit_Procfs_Interface(); ++ printk( KERN_INFO "exit_novfs Uninit_Procfs_Interface\n"); ++ ++ unregister_filesystem(&Novfs_fs_type); ++ printk( KERN_INFO "exit_novfs: Exit\n"); ++ ++ if (Novfs_CurrentMount) ++ { ++ Novfs_Free(Novfs_CurrentMount); ++ Novfs_CurrentMount = NULL; ++ } ++} ++ ++/*++======================================================================*/ ++int Novfs_lock_inode_cache( struct inode *i ) ++/* ++ * ++ * Arguments: struct inode *i - pointer to directory inode ++ * ++ * Returns: 0 - locked ++ * -1 - not locked ++ * ++ * Abstract: Locks the inode cache. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ int retVal = 0; ++ ++ DbgPrint("Novfs_lock_inode_cache: 0x%p\n", i); ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ down( &id->DirCacheLock ); ++ retVal = 1; ++ } ++ DbgPrint("Novfs_lock_inode_cache: return %d\n", retVal); ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++void Novfs_unlock_inode_cache( struct inode *i ) ++/* ++ * Arguments: struct inode *i - pointer to directory inode ++ * ++ * Returns: nothing ++ * ++ * Abstract: Unlocks inode cache. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ up( &id->DirCacheLock ); ++ } ++} ++ ++/*++======================================================================*/ ++int Novfs_enumerate_inode_cache( struct inode *i, struct list_head **iteration, ino_t *ino, PENTRY_INFO info) ++/* ++ * Arguments: struct inode *i - pointer to directory inode ++ * ++ * Returns: 0 - item found ++ * -1 - done ++ * ++ * Abstract: Unlocks inode cache. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *l=NULL; ++ int retVal = -1; ++ ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ if ( (NULL == iteration) || (NULL == *iteration) ) ++ { ++ l = id->DirCache.next; ++ } ++ else ++ { ++ l = *iteration; ++ } ++ ++ if (l == &id->DirCache) ++ { ++ l = NULL; ++ } ++ else ++ { ++ dc = list_entry(l, DIR_CACHE, list); ++ ++ *ino = dc->ino; ++ info->type = 0; ++ info->mode = dc->mode; ++ info->size = dc->size; ++ info->atime = dc->atime; ++ info->mtime = dc->mtime; ++ info->ctime = dc->ctime; ++ info->namelength = dc->nameLen; ++ memcpy(info->name, dc->name, dc->nameLen); ++ info->name[dc->nameLen] = '\0'; ++ retVal = 0; ++ ++ l = l->next; ++ } ++ } ++ *iteration = l; ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Novfs_get_entry( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ int retVal = -1; ++ char *n=""; ++ int nl=6; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ if (name && name->len) ++ { ++ n = (char *)name->name; ++ nl = name->len; ++ } ++ DbgPrint("Novfs_get_entry:\n" \ ++ " inode: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n", ++ i, nl, n, *ino); ++ ++ dc = Novfs_lookup_inode_cache(i, name, *ino); ++ if (dc) ++ { ++ dc->flags |= ENTRY_VALID; ++ retVal = 0; ++ *ino = dc->ino; ++ info->type = 0; ++ info->mode = dc->mode; ++ info->size = dc->size; ++ info->atime = dc->atime; ++ info->mtime = dc->mtime; ++ info->ctime = dc->ctime; ++ info->namelength = dc->nameLen; ++ memcpy(info->name, dc->name, dc->nameLen); ++ info->name[dc->nameLen] = '\0'; ++ retVal = 0; ++ } ++ } ++ DbgPrint("Novfs_get_entry: return %d\n", retVal); ++ return( retVal ); ++} ++ ++int Novfs_get_entry_by_pos( struct inode *i, loff_t pos, ino_t* ino, PENTRY_INFO info) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retVal = -1; ++ loff_t count = 0; ++ loff_t i_pos = pos - 2; ++ struct list_head *inter = NULL; ++ while( !Novfs_enumerate_inode_cache(i, &inter, ino, info)) ++ { ++ DbgPrint("Novfs_dir_readdir : Novfs_get_entry_by_pos : info->name = %s\n", info->name); ++ if(count == i_pos) ++ { ++ retVal = 0; ++ break; ++ } ++ else ++ count++; ++ } ++ ++ return retVal; ++} ++ ++/*++======================================================================*/ ++int Novfs_get_entry_time( struct inode *i, struct qstr *name, ino_t *ino, PENTRY_INFO info, u64 *EntryTime) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ int retVal = -1; ++ char *n=""; ++ int nl=6; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ if (name && name->len) ++ { ++ n = (char *)name->name; ++ nl = name->len; ++ } ++ DbgPrint("Novfs_get_entry:\n" \ ++ " inode: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n", ++ i, nl, n, *ino); ++ ++ dc = Novfs_lookup_inode_cache(i, name, *ino); ++ if (dc) ++ { ++ retVal = 0; ++ *ino = dc->ino; ++ info->type = 0; ++ info->mode = dc->mode; ++ info->size = dc->size; ++ info->atime = dc->atime; ++ info->mtime = dc->mtime; ++ info->ctime = dc->ctime; ++ info->namelength = dc->nameLen; ++ memcpy(info->name, dc->name, dc->nameLen); ++ info->name[dc->nameLen] = '\0'; ++ if (EntryTime) ++ { ++ *EntryTime = dc->jiffies; ++ } ++ retVal = 0; ++ } ++ } ++ DbgPrint("Novfs_get_entry: return %d\n", retVal); ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Novfs_get_remove_entry( struct inode *i, ino_t *ino, PENTRY_INFO info) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: This routine will return the first entry on the list ++ * and then remove it. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *l=NULL; ++ int retVal = -1; ++ ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ l = id->DirCache.next; ++ ++ if (l != &id->DirCache) ++ { ++ dc = list_entry(l, DIR_CACHE, list); ++ ++ *ino = dc->ino; ++ info->type = 0; ++ info->mode = dc->mode; ++ info->size = dc->size; ++ info->atime = dc->atime; ++ info->mtime = dc->mtime; ++ info->ctime = dc->ctime; ++ info->namelength = dc->nameLen; ++ memcpy(info->name, dc->name, dc->nameLen); ++ info->name[dc->nameLen] = '\0'; ++ retVal = 0; ++ ++ list_del( &dc->list ); ++ Novfs_Free( dc ); ++ DCCount--; ++ ++ } ++ } ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++void Novfs_invalidate_inode_cache( struct inode *i ) ++/* ++ * Arguments: struct inode *i - pointer to directory inode ++ * ++ * Returns: nothing ++ * ++ * Abstract: Marks all entries in the directory cache as invalid. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *l; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ list_for_each(l, &id->DirCache) ++ { ++ dc = list_entry(l, DIR_CACHE, list); ++ dc->flags &= ~ENTRY_VALID; ++ } ++ } ++} ++ ++/*++======================================================================*/ ++PDIR_CACHE Novfs_lookup_inode_cache( struct inode *i, struct qstr *name, ino_t ino ) ++/* ++ * Arguments: struct inode *i - pointer to directory inode ++ * struct qstr *name - pointer to name ++ * ino_t - inode number ++ * ++ * Returns: DIR_CACHE entry if match ++ * NULL - if there is no match. ++ * ++ * Abstract: Checks a inode directory to see if there are any enties ++ * matching name or ino. If name is specified then ino is ++ * not used. ino is use if name is not specified. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc, retVal=NULL; ++ struct list_head *l; ++ char *n=""; ++ int nl=6; ++ int hash=0; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ if (name && name->name) ++ { ++ nl = name->len; ++ n = (char *)name->name; ++ hash = name->hash; ++ } ++ DbgPrint("Novfs_lookup_inode_cache:\n" \ ++ " inode: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " hash: 0x%x\n" \ ++ " len: %d\n" \ ++ " ino: %d\n", ++ i, nl, n, hash, nl, ino); ++ ++ list_for_each(l, &id->DirCache) ++ { ++ dc = list_entry(l, DIR_CACHE, list); ++ if (name) ++ { ++ ++/* DbgPrint("Novfs_lookup_inode_cache: 0x%p\n" \ ++ " ino: %d\n" \ ++ " hash: 0x%x\n" \ ++ " len: %d\n" \ ++ " name: %.*s\n", ++ dc, dc->ino, dc->hash, dc->nameLen, dc->nameLen, dc->name); ++*/ ++ if ( (name->hash == dc->hash) && ++ (name->len == dc->nameLen) && ++ (0 == memcmp(name->name, dc->name, name->len)) ) ++ { ++ retVal = dc; ++ break; ++ } ++ } ++ else ++ { ++ if (ino == dc->ino) ++ { ++ retVal = dc; ++ break; ++ } ++ } ++ } ++ } ++ ++ DbgPrint("Novfs_lookup_inode_cache: return 0x%p\n", retVal); ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Novfs_lookup_validate( struct inode *i, struct qstr *name, ino_t ino ) ++/* ++ * Arguments: struct inode *i - pointer to directory inode ++ * struct qstr *name - pointer to name ++ * ino_t - inode number ++ * ++ * Returns: 0 if found ++ * !0 if not found ++ * ++ * Abstract: Checks a inode directory to see if there are any enties ++ * matching name or ino. If entry is found the valid bit ++ * is set. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ int retVal = -1; ++ char *n=""; ++ int nl=6; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ if (name && name->len) ++ { ++ n = (char *)name->name; ++ nl = name->len; ++ } ++ DbgPrint("Novfs_update_entry:\n" \ ++ " inode: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n", ++ i, nl, n, ino); ++ ++ dc = Novfs_lookup_inode_cache( i, name, ino ); ++ if (dc) ++ { ++ dc->flags |= ENTRY_VALID; ++ retVal = 0; ++ } ++ } ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Novfs_add_inode_entry( ++ struct inode *i, ++ struct qstr *name, ++ ino_t ino, ++ PENTRY_INFO info) ++/* ++ * Arguments: ++ * ++ * Returns: -ENOMEM - alloc error. ++ * 0 - success. ++ * ++ * Abstract: Added entry to directory cache. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE new; ++ int retVal = -ENOMEM; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ new = Novfs_Malloc(sizeof(DIR_CACHE)+name->len, GFP_KERNEL); ++ if (new) ++ { ++ DCCount++; ++ DbgPrint("Novfs_add_inode_entry:\n" \ ++ " inode: 0x%p\n" \ ++ " id: 0x%p\n" \ ++ " DC: 0x%p\n" \ ++ " new: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n" \ ++ " size: %lld\n" \ ++ " mode: 0x%x\n", ++ i, id, &id->DirCache, new, name->len, name->name, ino, info->size, info->mode); ++ ++ retVal = 0; ++ new->flags = ENTRY_VALID; ++ new->jiffies = get_jiffies_64(); ++ new->size = info->size; ++ new->mode = info->mode; ++ new->atime = info->atime; ++ new->mtime = info->mtime; ++ new->ctime = info->ctime; ++ new->ino = ino; ++ new->hash = name->hash; ++ new->nameLen = name->len; ++ memcpy(new->name, name->name, name->len); ++ new->name[new->nameLen] = '\0'; ++ list_add(&new->list, &id->DirCache); ++ ++/* list_for_each(l, &id->DirCache) ++ { ++ dc = list_entry(l, DIR_CACHE, list); ++ if ( dc->hash > new->hash ) ++ { ++ break; ++ } ++ } ++ ++ DbgPrint("Novfs_add_inode_entry: adding 0x%p to 0x%p\n", new, l); ++ list_add(&new->list, l); ++*/ ++ } ++ } ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Novfs_update_entry( struct inode *i, struct qstr *name, ino_t ino, PENTRY_INFO info) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ int retVal = -1; ++ char *n=""; ++ int nl=6; ++ char atime_buf[32]; ++ char mtime_buf[32]; ++ char ctime_buf[32]; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ ++ if (name && name->len) ++ { ++ n = (char *)name->name; ++ nl = name->len; ++ } ++ ctime_r(&info->atime.tv_sec, atime_buf); ++ ctime_r(&info->mtime.tv_sec, mtime_buf); ++ ctime_r(&info->ctime.tv_sec, ctime_buf); ++ DbgPrint("Novfs_update_entry:\n" \ ++ " inode: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n" \ ++ " size: %lld\n" \ ++ " atime: %s\n" \ ++ " mtime: %s\n" \ ++ " ctime: %s\n", ++ i, nl, n, ino, info->size, atime_buf, mtime_buf, ctime_buf); ++ ++ ++ dc = Novfs_lookup_inode_cache(i, name, ino); ++ if (dc) ++ { ++ retVal = 0; ++ dc->flags = ENTRY_VALID; ++ dc->jiffies = get_jiffies_64(); ++ dc->size = info->size; ++ dc->mode = info->mode; ++ dc->atime = info->atime; ++ dc->mtime = info->mtime; ++ dc->ctime = info->ctime; ++ ++ ctime_r(&dc->atime.tv_sec, atime_buf); ++ ctime_r(&dc->mtime.tv_sec, mtime_buf); ++ ctime_r(&dc->ctime.tv_sec, ctime_buf); ++ DbgPrint("Novfs_update_entry entry: 0x%x\n" \ ++ " flags: 0x%x\n" \ ++ " jiffies: %lld\n" \ ++ " ino: %d\n" \ ++ " size: %lld\n" \ ++ " mode: 0%o\n" \ ++ " atime: %s\n" \ ++ " mtime: %s %d\n" \ ++ " ctime: %s\n" \ ++ " hash: 0x%x\n" \ ++ " nameLen: %d\n" \ ++ " name: %s\n", ++ dc, dc->flags, dc->jiffies, dc->ino, dc->size, dc->mode, ++ atime_buf, mtime_buf, dc->mtime.tv_nsec, ctime_buf, dc->hash, dc->nameLen, dc->name); ++ } ++ } ++ DbgPrint("Novfs_update_entry: return %d\n", retVal); ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++void Novfs_remove_inode_entry( struct inode *i, struct qstr *name, ino_t ino) ++/* ++ * Arguments: ++ * ++ * Returns: nothing ++ * ++ * Abstract: Removes entry from directory cache. You can specify a name ++ * or an inode number. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ char *n=""; ++ int nl=6; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ dc = Novfs_lookup_inode_cache( i, name, ino ); ++ if (dc) ++ { ++ if (name && name->name) ++ { ++ nl = name->len; ++ n = (char *)name->name; ++ } ++ DbgPrint("Novfs_remove_inode_entry:\n" \ ++ " inode: 0x%p\n" \ ++ " id: 0x%p\n" \ ++ " DC: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n" \ ++ " entry: 0x%p\n" \ ++ " name: %.*s\n"\ ++ " ino: %d\n" \ ++ " next: 0x%p\n" \ ++ " prev: 0x%p\n", ++ i, id, &id->DirCache, nl, n, ino, dc, dc->nameLen, dc->name, dc->ino, dc->list.next, dc->list.prev); ++ list_del( &dc->list ); ++ Novfs_Free( dc ); ++ DCCount--; ++ ++ } ++ } ++} ++ ++/*++======================================================================*/ ++void Novfs_free_invalid_entries( struct inode *i ) ++/* ++ * Arguments: struct inode *i - pointer to directory inode. ++ * ++ * Returns: nothing ++ * ++ * Abstract: Frees all invalid entries in the directory cache. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *l; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ list_for_each( l, &id->DirCache ) ++ { ++ dc = list_entry( l, DIR_CACHE, list ); ++ if ( 0 == (dc->flags & ENTRY_VALID) ) ++ { ++ DbgPrint("Novfs_free_invalid_entries:\n" \ ++ " inode: 0x%p\n" \ ++ " id: 0x%p\n" \ ++ " entry: 0x%p\n" \ ++ " name: %.*s\n" \ ++ " ino: %d\n", ++ i, id, dc, dc->nameLen, dc->name, dc->ino); ++ l = l->prev; ++ list_del( &dc->list ); ++ Novfs_Free( dc ); ++ DCCount--; ++ } ++ } ++ } ++} ++ ++/*++======================================================================*/ ++void Novfs_free_inode_cache( struct inode *i ) ++/* ++ * Arguments: struct inode *i - pointer to directory inode. ++ * ++ * Returns: nothing ++ * ++ * Abstract: Frees all entries in the inode cache. ++ * ++ * Notes: DirCacheLock should be held before calling this routine. ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *l; ++ ++ if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ { ++ list_for_each( l, &id->DirCache ) ++ { ++ dc = list_entry( l, DIR_CACHE, list ); ++ l = l->prev; ++ list_del( &dc->list ); ++ Novfs_Free( dc ); ++ DCCount--; ++ } ++ } ++} ++ ++/*++======================================================================*/ ++int ++NO_TRACE ++Novfs_dump_inode_cache(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++#ifdef CONFIG_KDB ++ struct inode *inode=NULL; ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *l; ++ char atime_buf[32]; ++ char mtime_buf[32]; ++ char ctime_buf[32]; ++ ++ if (Novfs_root) ++ { ++ inode = Novfs_root->d_inode; ++ } ++ ++ if (argc > 0) ++ { ++ inode = (void *)simple_strtoul(argv[1], NULL, 0); ++ } ++ ++ kdb_printf("Inode: 0x%p\n", inode); ++ if (inode) ++ { ++ id = inode->u.generic_ip; ++ kdb_printf("INODE_DATA: 0x%p\n", id); ++ ++ if ( id && id->DirCache.next ) ++ { ++ list_for_each(l, &id->DirCache) ++ { ++ dc = list_entry(l, DIR_CACHE, list); ++ ctime_r(&dc->atime.tv_sec, atime_buf); ++ ctime_r(&dc->mtime.tv_sec, mtime_buf); ++ ctime_r(&dc->ctime.tv_sec, ctime_buf); ++ ++ DbgPrint("Cache Entry: 0x%p\n" \ ++ " flags: 0x%x\n" \ ++ " jiffies: %llu\n" \ ++ " ino: %u\n" \ ++ " size: %llu\n" \ ++ " mode: 0%o\n" \ ++ " atime: %s\n" \ ++ " mtime: %s\n" \ ++ " ctime: %s\n" \ ++ " hash: 0x%x\n" \ ++ " len: %d\n" \ ++ " name: %s\n", ++ dc, dc->flags, dc->jiffies, ++ dc->ino, dc->size, dc->mode, ++ atime_buf, mtime_buf, ctime_buf, ++ dc->hash, dc->nameLen, dc->name); ++ } ++ } ++ } ++#endif ++ return(0); ++} ++ ++/*++======================================================================*/ ++void ++NO_TRACE ++Novfs_dump_inode( void *pf ) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ struct inode *inode; ++ void (*pfunc)(char *Fmt, ...) = pf; ++ PINODE_DATA id; ++ PDIR_CACHE dc; ++ struct list_head *il, *l; ++ char atime_buf[32]; ++ char mtime_buf[32]; ++ char ctime_buf[32]; ++ unsigned long icnt=0, dccnt=0; ++ ++ down( &InodeList_lock ); ++ list_for_each(il, &InodeList) ++ { ++ id = list_entry(il, INODE_DATA, IList); ++ inode = id->Inode; ++ if (inode) ++ { ++ icnt++; ++ ++ pfunc("Inode=0x%x I_ino=%d\n", inode, inode->i_ino); ++ ++ pfunc(" atime=%s\n", ctime_r(&inode->i_atime.tv_sec, atime_buf)); ++ pfunc(" ctime=%s\n", ctime_r(&inode->i_mtime.tv_sec, atime_buf)); ++ pfunc(" mtime=%s\n", ctime_r(&inode->i_ctime.tv_sec, atime_buf)); ++ pfunc(" size=%lld\n", inode->i_size); ++ pfunc(" mode=0%o\n", inode->i_mode); ++ } ++ ++ pfunc(" INODE_DATA: 0x%p Name=%s Scope=0x%p\n", id, id->Name, id->Scope); ++ ++ if (id->DirCache.next ) ++ { ++ list_for_each(l, &id->DirCache) ++ { ++ dccnt++; ++ dc = list_entry(l, DIR_CACHE, list); ++ ctime_r(&dc->atime.tv_sec, atime_buf); ++ ctime_r(&dc->mtime.tv_sec, mtime_buf); ++ ctime_r(&dc->ctime.tv_sec, ctime_buf); ++ ++ pfunc(" Cache Entry: 0x%p\n" \ ++ " flags: 0x%x\n" \ ++ " jiffies: %llu\n" \ ++ " ino: %u\n" \ ++ " size: %llu\n" \ ++ " mode: 0%o\n" \ ++ " atime: %s\n" \ ++ " mtime: %s\n" \ ++ " ctime: %s\n" \ ++ " hash: 0x%x\n" \ ++ " len: %d\n" \ ++ " name: %s\n", ++ dc, dc->flags, dc->jiffies, ++ dc->ino, dc->size, dc->mode, ++ atime_buf, mtime_buf, ctime_buf, ++ dc->hash, dc->nameLen, dc->name); ++ } ++ } ++ } ++ up( &InodeList_lock ); ++ ++ pfunc("Inodes: %d(%d) DirCache: %d(%d)\n", InodeCount, icnt, DCCount, dccnt ); ++ ++} ++ ++module_init(init_novfs) ++module_exit(exit_novfs) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Novell Inc."); ++MODULE_DESCRIPTION("Novell NetWare Client for Linux"); ++MODULE_VERSION( NOVFS_VERSION_STRING ); +diff -uNr src.old/src/m src/src/m +--- src.old/src/m 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/m 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,12 @@ ++#!/bin/sh ++ ++VERSION=`uname -r` ++ ++make -C /usr/src/linux SUBDIRS=$PWD modules ++ ++if [ -e novfs.ko ] ++then ++ mkdir -p -m 755 /lib/modules/$VERSION/kernel/fs/novfs ++ echo "copying novfs.ko to /lib/modules/$VERSION/kernel/fs/novfs" ++ cp novfs.ko /lib/modules/$VERSION/kernel/fs/novfs ++fi +diff -uNr src.old/src/mk_novfs src/src/mk_novfs +--- src.old/src/mk_novfs 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/mk_novfs 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,114 @@ ++#!/bin/sh ++ ++RVAL=1 ++TO_BUILD=1 ++ ++BUILD_TYPE=modules ++ ++if [ $1 ] ++then ++ if [ "$1" = "force" ] ++ then ++ FORCE=1 ++ else ++ BUILD_TYPE=$1 ++ FORCE=0 ++ fi ++else ++ FORCE=0 ++fi ++ ++platform=`uname -i` ++ ++if [ -d /usr/src/linux-obj/$platform ] ++then ++ for i in $(ls /usr/src/linux-obj/$platform) ++ do ++ TO_BUILD=1 ++ VERSION=`cat /usr/src/linux-obj/$platform/$i/include/linux/version.h |grep UTS_RELEASE |awk '{printf("%s\n", substr($3, 2,length($3)-2))}'` ++ NOVFS_PATH=/lib/modules/$VERSION/kernel/fs/novfs ++ ++ if [ -e /lib/modules/$VERSION/extra/novfs.ko ] ++ then ++ NOVFS_PATH=/lib/modules/$VERSION/extra ++ ++ else ++ if [ -e /lib/modules/$VERSION/updates/novfs.ko ] ++ then ++ NOVFS_PATH=/lib/modules/$VERSION/updates ++ ++ fi ++ fi ++ ++ if [ -d /lib/modules/$VERSION ] ++ then ++ ++ if [ -e $NOVFS_PATH/novfs.ko ] ++ then ++ CUR_NOVFS_VERSION=`od --strings=8 $NOVFS_PATH/novfs.ko |grep version= |awk '{split($2,a,"="); if("version"==a[1]) printf("%s", a[2])}'` ++ CUR_NOVFS_VFS_MAJOR=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"."); printf("%d", a[1])}'` ++ CUR_NOVFS_VFS_MINOR=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"."); printf("%d", a[2])}'` ++ CUR_NOVFS_VFS_SUB=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"."); printf("%d", a[3])}'` ++ CUR_NOVFS_VFS_RELEASE=`echo $CUR_NOVFS_VERSION |awk '{split($0,a,"-"); printf("%d", a[2])}'` ++ ++ NOVFS_VFS_MAJOR=`cat Makefile |grep 'NOVFS_VFS_MAJOR =' |awk '{printf("%d", $3)}'` ++ NOVFS_VFS_MINOR=`cat Makefile |grep 'NOVFS_VFS_MINOR =' |awk '{printf("%d", $3)}'` ++ NOVFS_VFS_SUB=`cat Makefile |grep 'NOVFS_VFS_SUB =' |awk '{printf("%d", $3)}'` ++ NOVFS_VFS_RELEASE=`cat Makefile |grep 'NOVFS_VFS_RELEASE =' |awk '{printf("%d", $3)}'` ++ NOVFS_VFS_VERSION="$NOVFS_VFS_MAJOR.$NOVFS_VFS_MINOR.$NOVFS_VFS_SUB-$NOVFS_VFS_RELEASE" ++ ++ TO_BUILD=0 ++ ++ if [ $NOVFS_VFS_MAJOR -gt $CUR_NOVFS_VFS_MAJOR ] ++ then ++ TO_BUILD=1 ++ else ++ if [ $NOVFS_VFS_MAJOR -eq $CUR_NOVFS_VFS_MAJOR ] ++ then ++ if [ $NOVFS_VFS_MINOR -gt $CUR_NOVFS_VFS_MINOR ] ++ then ++ TO_BUILD=1 ++ else ++ if [ $NOVFS_VFS_MINOR -eq $CUR_NOVFS_VFS_MINOR ] ++ then ++ if [ $NOVFS_VFS_SUB -gt $CUR_NOVFS_VFS_SUB ] ++ then ++ TO_BUILD=1 ++ else ++ if [ $NOVFS_VFS_SUB -eq $CUR_NOVFS_VFS_SUB ] ++ then ++ if [ $NOVFS_VFS_RELEASE -gt $CUR_NOVFS_VFS_RELEASE ] ++ then ++ TO_BUILD=1 ++ fi ++ fi ++ fi ++ fi ++ fi ++ fi ++ fi ++ fi ++ ++ if [ $FORCE -eq 1 ] ++ then ++ TO_BUILD=1; ++ fi ++ ++ if [ $TO_BUILD -eq 1 ] ++ then ++ echo Building novfs.ko for $VERSION ++ make -C /usr/src/linux-obj/$platform/$i SUBDIRS=$PWD $BUILD_TYPE ++ RVAL=$? ++ if [ -e novfs.ko ] ++ then ++ mkdir -p -m 755 $NOVFS_PATH ++ echo "copying novfs.ko to $NOVFS_PATH" ++ cp novfs.ko $NOVFS_PATH ++ RVAL=$? ++ fi ++ fi ++ fi ++ done ++fi ++exit $RVAL ++ +diff -uNr src.old/src/nwcapi.c src/src/nwcapi.c +--- src.old/src/nwcapi.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/nwcapi.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,2410 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: nwcapi.c ++ * Version: v1.00 ++ * Author: James Turner/Richard Williams ++ * ++ * Abstract: This module contains functions used to interface to ++ * the library interface of the daemon. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++ ++/*===[ Include files specific to this module ]============================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nwcapi.h" ++#include "nwerror.h" ++#include "commands.h" ++ ++#include "vfs.h" ++ ++/*===[ External data ]====================================================*/ ++ ++/*===[ External prototypes ]==============================================*/ ++ ++extern int DbgPrint( char *Fmt, ... ); ++extern void mydump(int size, void *dumpptr); ++ ++extern session_t Scope_Get_SessionId( void *Scope ); ++extern int Queue_Daemon_Command(void *request, u_long reqlen, void *data, int dlen, void **reply, u_long *replen, int interruptible); ++ ++extern int do_login(NclString *Server, NclString *Username, NclString *Password, u_long *lgnId, session_t Session); ++ ++void GetUserData(NwcScanConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply); ++void GetConnData(NwcGetConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply); ++ ++/*===[ Manifest constants ]===============================================*/ ++ ++/*===[ Type definitions ]=================================================*/ ++ ++/*===[ Function prototypes ]==============================================*/ ++ ++/*===[ Global variables ]=================================================*/ ++ ++/*===[ Code ]=============================================================*/ ++ ++/*++======================================================================*/ ++ ++/*++======================================================================*/ ++int NwOpenConnByName(PXPLAT pdata, u_long *Handle, session_t Session) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCOpenConnByName openConn, connReply; ++NwcOpenConnByName ocbn; ++u_long retCode = 0, cmdlen, datalen, replylen, cpylen; ++char *data; ++ ++ cpylen = copy_from_user(&ocbn, pdata->reqData, sizeof(ocbn)); ++ datalen = sizeof(*openConn) + strlen_user(ocbn.pName->pString) + strlen_user(ocbn.pServiceType); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_OPEN_CONN_BY_NAME; ++ ++ cmd->dataLen = datalen; ++ openConn = (PNwdCOpenConnByName)cmd->data; ++ ++ openConn->nameLen = strlen_user(ocbn.pName->pString); ++ openConn->serviceLen = strlen_user(ocbn.pServiceType); ++ openConn->uConnFlags = ocbn.uConnFlags; ++ openConn->ConnHandle = ocbn.ConnHandle; ++ data = (char *)openConn; ++ data += sizeof(*openConn); ++ openConn->oName = sizeof(*openConn); ++ ++ openConn->oServiceType = openConn->oName + openConn->nameLen; ++ cpylen = copy_from_user(data, ocbn.pName->pString, openConn->nameLen); ++ data += openConn->nameLen; ++ cpylen = copy_from_user(data, ocbn.pServiceType, openConn->serviceLen); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ /* ++ * we got reply data from the daemon ++ */ ++ connReply = (PNwdCOpenConnByName)reply->data; ++ retCode = reply->Reply.ErrorCode; ++ if (!retCode) ++ { ++ /* ++ * we got valid data. ++ */ ++ connReply = (PNwdCOpenConnByName)reply->data; ++ ocbn.RetConnHandle = connReply->newConnHandle; ++ *Handle = connReply->newConnHandle; ++ cpylen = copy_to_user(pdata->reqData, &ocbn, sizeof(ocbn)); ++ DbgPrint("New Conn Handle = %X\n", connReply->newConnHandle); ++ } ++ Novfs_Free(reply); ++ } ++ ++ Novfs_Free(cmd); ++ } ++ ++ return((int)retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwOpenConnByAddr(PXPLAT pdata, u_long *Handle, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCOpenConnByAddr openConn, connReply; ++NwcOpenConnByAddr ocba; ++NwcTranAddr tranAddr; ++u_long retCode = 0, cmdlen, datalen, replylen, cpylen; ++char addr[MAX_ADDRESS_LENGTH]; ++ ++ cpylen = copy_from_user(&ocba, pdata->reqData, sizeof(ocba)); ++ datalen = sizeof(*openConn); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_OPEN_CONN_BY_ADDRESS; ++ cmd->dataLen = datalen; ++ openConn = (PNwdCOpenConnByAddr)cmd->data; ++ ++ cpylen = copy_from_user(&tranAddr, ocba.pTranAddr, sizeof(tranAddr)); ++ ++ DbgPrint("NwOpenConnByAddr: tranAddr\n"); ++ mydump(sizeof(tranAddr), &tranAddr); ++ ++ openConn->TranAddr.uTransportType = tranAddr.uTransportType; ++ openConn->TranAddr.uAddressLength = tranAddr.uAddressLength; ++ memset(addr, 0xcc, sizeof(addr)-1); ++ ++ cpylen = copy_from_user(addr, tranAddr.puAddress, tranAddr.uAddressLength); ++ ++ DbgPrint("NwOpenConnByAddr: addr\n"); ++ mydump(sizeof(addr), addr); ++ ++ openConn->TranAddr.oAddress = *(u_long *)(&addr[2]); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ /* ++ * we got reply data from the daemon ++ */ ++ connReply = (PNwdCOpenConnByAddr)reply->data; ++ retCode = reply->Reply.ErrorCode; ++ if (!retCode) ++ { ++ /* ++ * we got valid data. ++ */ ++ connReply = (PNwdCOpenConnByAddr)reply->data; ++ ocba.ConnHandle = connReply->ConnHandle; ++ *Handle = connReply->ConnHandle; ++ cpylen = copy_to_user(pdata->reqData, &ocba, sizeof(ocba)); ++ DbgPrint("New Conn Handle = %X\n", connReply->ConnHandle); ++ } ++ Novfs_Free(reply); ++ } ++ ++ Novfs_Free(cmd); ++ } ++ ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwOpenConnByRef(PXPLAT pdata, u_long *Handle, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCOpenConnByRef openConn; ++NwcOpenConnByReference ocbr; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ ++ cpylen = copy_from_user(&ocbr, pdata->reqData, sizeof(ocbr)); ++ datalen = sizeof(*openConn); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_OPEN_CONN_BY_REFERENCE; ++ cmd->dataLen = datalen; ++ openConn = (PNwdCOpenConnByRef)cmd->data; ++ ++ memcpy(openConn, &ocbr, sizeof(ocbr)); ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ /* ++ * we got reply data from the daemon ++ */ ++ openConn = (PNwdCOpenConnByRef)reply->data; ++ retCode = reply->Reply.ErrorCode; ++ if (!retCode) ++ { ++ /* ++ * we got valid data. ++ */ ++ ocbr.ConnHandle = openConn->ConnHandle; ++ *Handle = openConn->ConnHandle; ++ ++ cpylen = copy_to_user(pdata->reqData, &ocbr, sizeof(ocbr)); ++ DbgPrint("New Conn Handle = %X\n", openConn->ConnHandle); ++ } ++ Novfs_Free(reply); ++ } ++ ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwRawSend(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++NwcRequest xRequest; ++PNwcFrag frag, cFrag, reqFrag; ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++u_long x, totalLen; ++PNwdCNCPReq ncpData; ++PNwdCNCPRep ncpReply; ++u_char *reqData; ++unsigned long actualReplyLength=0; ++ ++ DbgPrint("[XPLAT] Process Raw NCP Send\n"); ++ cpylen = copy_from_user(&xRequest, pdata->reqData, sizeof(xRequest)); ++ ++ /* ++ * Figure out the length of the request ++ */ ++ frag = Novfs_Malloc(xRequest.uNumReplyFrags * sizeof(NwcFrag), GFP_KERNEL); ++ ++ DbgPrint("[XPLAT RawNCP] - Reply Frag Count 0x%X\n", xRequest.uNumReplyFrags); ++ ++ if (!frag) ++ return(retCode); ++ ++ cpylen = copy_from_user(frag, xRequest.pReplyFrags, xRequest.uNumReplyFrags * sizeof(NwcFrag)); ++ totalLen = 0; ++ ++ cFrag = frag; ++ for (x = 0; x < xRequest.uNumReplyFrags; x ++) ++ { ++ DbgPrint("[XPLAT - RawNCP] - Frag Len = %d\n", cFrag->uLength); ++ totalLen += cFrag->uLength; ++ cFrag++; ++ } ++ ++ ++ DbgPrint("[XPLAT - RawNCP] - totalLen = %d\n", totalLen); ++ datalen = 0; ++ reqFrag = Novfs_Malloc(xRequest.uNumRequestFrags * sizeof(NwcFrag), GFP_KERNEL); ++ if (!reqFrag) ++ { ++ Novfs_Free(frag); ++ return(retCode); ++ } ++ ++ cpylen = copy_from_user(reqFrag, xRequest.pRequestFrags, xRequest.uNumRequestFrags * sizeof(NwcFrag)); ++ cFrag = reqFrag; ++ for (x = 0; x < xRequest.uNumRequestFrags; x ++) ++ { ++ datalen += cFrag->uLength; ++ cFrag++; ++ } ++ ++ /* ++ * Allocate the cmd Request ++ */ ++ cmdlen = datalen + sizeof(*cmd) + sizeof(*ncpData); ++ DbgPrint("[XPLAT RawNCP] - Frag Count 0x%X\n", xRequest.uNumRequestFrags); ++ DbgPrint("[XPLAT RawNCP] - Total Command Data Len = %x\n", cmdlen); ++ ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_RAW_NCP_REQUEST; ++ ++ /* ++ * build the NCP Request ++ */ ++ cmd->dataLen = cmdlen - sizeof(*cmd); ++ ncpData = (PNwdCNCPReq)cmd->data; ++ ncpData->replyLen = totalLen; ++ ncpData->requestLen = datalen; ++ ncpData->ConnHandle = xRequest.ConnHandle; ++ ncpData->function = xRequest.uFunction; ++ ++ ++ reqData = ncpData->data; ++ cFrag = reqFrag; ++ ++ for (x = 0; x < xRequest.uNumRequestFrags; x ++) ++ { ++ cpylen = copy_from_user(reqData, cFrag->pData, cFrag->uLength); ++ reqData += cFrag->uLength; ++ cFrag++; ++ } ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ DbgPrint("RawNCP - reply = %x\n", reply); ++ DbgPrint("RawNCP - retCode = %x\n", retCode); ++ ++ if (reply) ++ { ++ /* ++ * we got reply data from the daemon ++ */ ++ ncpReply = (PNwdCNCPRep)reply->data; ++ retCode = reply->Reply.ErrorCode; ++ ++ DbgPrint("RawNCP - Reply Frag Count 0x%X\n", xRequest.uNumReplyFrags); ++ ++ /* ++ * We need to copy the reply frags to the packet. ++ */ ++ reqData = ncpReply->data; ++ cFrag = frag; ++ ++ totalLen = ncpReply->replyLen; ++ for (x = 0; x < xRequest.uNumReplyFrags; x ++) ++ { ++ ++ DbgPrint("RawNCP - Copy Frag %d: 0x%X\n", x, cFrag->uLength); ++ ++ datalen = min(cFrag->uLength, totalLen); ++ ++ cpylen = copy_to_user(cFrag->pData, reqData, datalen); ++ totalLen -= datalen; ++ reqData += datalen; ++ actualReplyLength += datalen; ++ ++ cFrag++; ++ } ++ ++ Novfs_Free(reply); ++ } ++ else ++ { ++ retCode = -EIO; ++ } ++ ++ Novfs_Free(cmd); ++ } ++ xRequest.uActualReplyLength = actualReplyLength; ++ cpylen = copy_to_user(pdata->reqData, &xRequest, sizeof(xRequest)); ++ ++ Novfs_Free(reqFrag); ++ Novfs_Free(frag); ++ ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int NwConnClose(PXPLAT pdata, u_long *Handle, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcCloseConn cc; ++PNwdCCloseConn nwdClose; ++u_long retCode = 0, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&cc, pdata->reqData, sizeof(cc)); ++ ++ datalen = sizeof(*nwdClose); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_CLOSE_CONN; ++ ++ nwdClose = (PNwdCCloseConn)cmd->data; ++ cmd->dataLen = sizeof(*nwdClose); ++ nwdClose->ConnHandle = cc.ConnHandle; ++ *Handle = cc.ConnHandle; ++ ++ /* ++ * send the request ++ */ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, 0); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwSysConnClose(PXPLAT pdata, u_long *Handle, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcCloseConn cc; ++PNwdCCloseConn nwdClose; ++u_long retCode = 0, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&cc, pdata->reqData, sizeof(cc)); ++ ++ datalen = sizeof(*nwdClose); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SYS_CLOSE_CONN; ++ ++ nwdClose = (PNwdCCloseConn)cmd->data; ++ cmd->dataLen = sizeof(*nwdClose); ++ nwdClose->ConnHandle = cc.ConnHandle; ++ *Handle = cc.ConnHandle; ++ ++ /* ++ * send the request ++ */ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, 0); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwLoginIdentity(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++NwcLoginIdentity lgn, *plgn; ++int retCode = -ENOMEM; ++NclString server; ++NclString username; ++NclString password; ++u_long cpylen; ++NwcString nwcStr; ++ ++ cpylen = copy_from_user(&lgn, pdata->reqData, sizeof(lgn)); ++ ++ DbgPrint("NwLoginIdentity:\n"); ++ mydump(sizeof(lgn), &lgn); ++ ++ ++ ++ cpylen = copy_from_user(&nwcStr, lgn.pDomainName, sizeof(nwcStr)); ++ DbgPrint("NwLoginIdentity: DomainName\n"); ++ mydump(sizeof(nwcStr), &nwcStr); ++ ++ if ( (server.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL)) ) ++ { ++ server.type = nwcStr.DataType; ++ server.len = nwcStr.DataLen; ++ if ( !copy_from_user((void *)server.buffer, nwcStr.pBuffer, server.len) ) ++ { ++ DbgPrint("NwLoginIdentity: Server\n"); ++ mydump(server.len, server.buffer); ++ ++ cpylen = copy_from_user(&nwcStr, lgn.pObjectName, sizeof(nwcStr)); ++ DbgPrint("NwLoginIdentity: ObjectName\n"); ++ mydump(sizeof(nwcStr), &nwcStr); ++ ++ if ( (username.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL)) ) ++ { ++ username.type = nwcStr.DataType; ++ username.len = nwcStr.DataLen; ++ if ( !copy_from_user((void *)username.buffer, nwcStr.pBuffer, username.len) ) ++ { ++ DbgPrint("NwLoginIdentity: User\n"); ++ mydump(username.len, username.buffer); ++ ++ cpylen = copy_from_user(&nwcStr, lgn.pPassword, sizeof(nwcStr)); ++ DbgPrint("NwLoginIdentity: Password\n"); ++ mydump(sizeof(nwcStr), &nwcStr); ++ ++ if ( (password.buffer = Novfs_Malloc(nwcStr.DataLen, GFP_KERNEL)) ) ++ { ++ password.type = nwcStr.DataType; ++ password.len = nwcStr.DataLen; ++ if ( !copy_from_user((void *)password.buffer, nwcStr.pBuffer, password.len) ) ++ { ++ retCode = do_login(&server, &username, &password, (u_long *)&lgn.AuthenticationId, Session); ++ if (retCode) ++ { ++ lgn.AuthenticationId = 0; ++ } ++ ++ plgn = (NwcLoginIdentity *)pdata->reqData; ++ cpylen = copy_to_user(&plgn->AuthenticationId, &lgn.AuthenticationId, sizeof(plgn->AuthenticationId)); ++ ++ } ++ memset(password.buffer, 0, password.len); ++ Novfs_Free(password.buffer); ++ } ++ } ++ memset(username.buffer, 0, username.len); ++ Novfs_Free(username.buffer); ++ } ++ } ++ Novfs_Free(server.buffer); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int NwAuthConnWithId(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++NwcAuthenticateWithId pauth; ++PNwdCAuthenticateWithId pDauth; ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ datalen = sizeof(*pDauth); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_AUTHENTICATE_CONN_WITH_ID; ++ ++ ++ cpylen = copy_from_user(&pauth, pdata->reqData, sizeof(pauth)); ++ ++ pDauth = (PNwdCAuthenticateWithId)cmd->data; ++ cmd->dataLen = datalen; ++ pDauth->AuthenticationId = pauth.AuthenticationId; ++ pDauth->ConnHandle = pauth.ConnHandle; ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int NwLicenseConn(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcLicenseConn lisc; ++PNwdCLicenseConn pDLisc; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ datalen = sizeof(*pDLisc); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_LICENSE_CONN; ++ ++ ++ cpylen = copy_from_user(&lisc, pdata->reqData, sizeof(lisc)); ++ ++ pDLisc = (PNwdCLicenseConn)cmd->data; ++ cmd->dataLen = datalen; ++ pDLisc->ConnHandle = lisc.ConnHandle; ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++} ++ ++ ++/*++======================================================================*/ ++int NwLogoutIdentity(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcLogoutIdentity logout; ++PNwdCLogoutIdentity pDLogout; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ datalen = sizeof(*pDLogout); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_LOGOUT_IDENTITY; ++ ++ cpylen = copy_from_user(&logout, pdata->reqData, sizeof(logout)); ++ ++ pDLogout = (PNwdCLogoutIdentity)cmd->data; ++ cmd->dataLen = datalen; ++ pDLogout->AuthenticationId = logout.AuthenticationId; ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int NwUnlicenseConn(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCUnlicenseConn pUconn; ++NwcUnlicenseConn ulc; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ ++ cpylen = copy_from_user(&ulc, pdata->reqData, sizeof(ulc)); ++ datalen = sizeof(*pUconn); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_UNLICENSE_CONN; ++ cmd->dataLen = datalen; ++ pUconn = (PNwdCUnlicenseConn)cmd->data; ++ ++ pUconn->ConnHandle = ulc.ConnHandle; ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ /* ++ * we got reply data from the daemon ++ */ ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++ ++/*++======================================================================*/ ++int NwUnAuthenticate(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcUnauthenticate auth; ++PNwdCUnauthenticate pDAuth; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ datalen = sizeof(*pDAuth); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_UNAUTHENTICATE_CONN; ++ ++ cpylen = copy_from_user(&auth, pdata->reqData, sizeof(auth)); ++ ++ pDAuth = (PNwdCUnauthenticate)cmd->data; ++ cmd->dataLen = datalen; ++ pDAuth->AuthenticationId = auth.AuthenticationId; ++ pDAuth->ConnHandle = auth.ConnHandle; ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++ ++/*++======================================================================*/ ++int NwGetConnInfo(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcGetConnInfo connInfo; ++PNwdCGetConnInfo pDConnInfo; ++u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; ++ ++ cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ cpylen = copy_from_user(&connInfo, pdata->reqData, sizeof(NwcGetConnInfo)); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_GET_CONN_INFO; ++ ++ pDConnInfo = (PNwdCGetConnInfo)cmd->data; ++ ++ pDConnInfo->ConnHandle = connInfo.ConnHandle; ++ pDConnInfo->uInfoLevel = connInfo.uInfoLevel; ++ pDConnInfo->uInfoLength = connInfo.uInfoLength; ++ cmd->dataLen = sizeof(*pDConnInfo); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ GetConnData(&connInfo, cmd, reply); ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(retCode); ++ ++} ++ ++ ++/*++======================================================================*/ ++int NwSetConnInfo(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcSetConnInfo connInfo; ++PNwdCSetConnInfo pDConnInfo; ++u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; ++ ++ cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ cpylen = copy_from_user(&connInfo, pdata->reqData, sizeof(NwcSetConnInfo)); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SET_CONN_INFO; ++ ++ pDConnInfo = (PNwdCSetConnInfo)cmd->data; ++ ++ pDConnInfo->ConnHandle = connInfo.ConnHandle; ++ pDConnInfo->uInfoLevel = connInfo.uInfoLevel; ++ pDConnInfo->uInfoLength = connInfo.uInfoLength; ++ cmd->dataLen = sizeof(*pDConnInfo); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwGetIdentityInfo(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcGetIdentityInfo qidInfo, *gId; ++PNwdCGetIdentityInfo idInfo; ++NwcString xferStr; ++char *str; ++u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; ++ ++ cmdlen = sizeof(*cmd) + sizeof(*idInfo); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ cpylen = copy_from_user(&qidInfo, pdata->reqData, sizeof(qidInfo)); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_GET_IDENTITY_INFO; ++ ++ idInfo = (PNwdCGetIdentityInfo)cmd->data; ++ ++ idInfo->AuthenticationId = qidInfo.AuthenticationId; ++ cmd->dataLen = sizeof(*idInfo); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ ++ if (!reply->Reply.ErrorCode) ++ { ++ /* ++ * Save the return info to the user structure. ++ */ ++ gId = pdata->reqData; ++ idInfo = (PNwdCGetIdentityInfo)reply->data; ++ cpylen = copy_to_user(&gId->AuthenticationId, &idInfo->AuthenticationId, sizeof(idInfo->AuthenticationId)); ++ cpylen = copy_to_user(&gId->AuthType, &idInfo->AuthType, sizeof(idInfo->AuthType)); ++ cpylen = copy_to_user(&gId->IdentityFlags, &idInfo->IdentityFlags, sizeof(idInfo->IdentityFlags)); ++ cpylen = copy_to_user(&gId->NameType, &idInfo->NameType, sizeof(idInfo->NameType)); ++ cpylen = copy_to_user(&gId->ObjectType, &idInfo->ObjectType, sizeof(idInfo->ObjectType)); ++ ++ cpylen = copy_from_user(&xferStr, gId->pDomainName, sizeof(NwcString)); ++ str = (char *)((char *)reply->data + idInfo->pDomainNameOffset); ++ cpylen = copy_to_user(xferStr.pBuffer, str, idInfo->domainLen); ++ xferStr.DataType = NWC_STRING_TYPE_ASCII; ++ xferStr.DataLen = idInfo->domainLen; ++ cpylen = copy_to_user(gId->pDomainName, &xferStr, sizeof(NwcString)); ++ ++ ++ cpylen = copy_from_user(&xferStr, gId->pObjectName, sizeof(NwcString)); ++ str = (char *)((char *)reply->data + idInfo->pObjectNameOffset); ++ cpylen = copy_to_user(xferStr.pBuffer, str, idInfo->objectLen); ++ xferStr.DataLen = idInfo->objectLen - 1; ++ xferStr.DataType = NWC_STRING_TYPE_ASCII; ++ cpylen = copy_to_user(gId->pObjectName, &xferStr, sizeof(NwcString)); ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++int NwScanConnInfo(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcScanConnInfo connInfo, *rInfo; ++PNwdCScanConnInfo pDConnInfo; ++u_long retCode = -ENOMEM, cmdlen, replylen, cpylen; ++u_char *localData; ++ ++ cpylen = copy_from_user(&connInfo, pdata->reqData, sizeof(NwcScanConnInfo)); ++ ++ cmdlen = sizeof(*cmd) + sizeof(*pDConnInfo) + connInfo.uScanInfoLen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SCAN_CONN_INFO; ++ ++ pDConnInfo = (PNwdCScanConnInfo)cmd->data; ++ ++ DbgPrint("NwScanConnInfo: Input Data\n"); ++ DbgPrint("connInfo.uScanIndex = 0x%X\n", connInfo.uScanIndex); ++ DbgPrint("connInfo.uConnectionReference = 0x%X\n", connInfo.uConnectionReference); ++ DbgPrint("connInfo.uScanInfoLevel = 0x%X\n", connInfo.uScanInfoLevel); ++ DbgPrint("connInfo.uScanInfoLen = 0x%X\n", connInfo.uScanInfoLen); ++ DbgPrint("connInfo.uReturnInfoLength = 0x%X\n", connInfo.uReturnInfoLength); ++ DbgPrint("connInfo.uReturnInfoLevel = 0x%X\n", connInfo.uReturnInfoLevel); ++ DbgPrint("connInfo.uScanFlags = 0x%X\n", connInfo.uScanFlags); ++ ++ ++ pDConnInfo->uScanIndex = connInfo.uScanIndex; ++ pDConnInfo->uConnectionReference = connInfo.uConnectionReference; ++ pDConnInfo->uScanInfoLevel = connInfo.uScanInfoLevel; ++ pDConnInfo->uScanInfoLen = connInfo.uScanInfoLen; ++ pDConnInfo->uReturnInfoLength = connInfo.uReturnInfoLength; ++ pDConnInfo->uReturnInfoLevel = connInfo.uReturnInfoLevel; ++ pDConnInfo->uScanFlags = connInfo.uScanFlags; ++ ++ if (pDConnInfo->uScanInfoLen) ++ { ++ localData = (u_char *)pDConnInfo; ++ pDConnInfo->uScanConnInfoOffset = sizeof(*pDConnInfo); ++ localData += pDConnInfo->uScanConnInfoOffset; ++ cpylen = copy_from_user(localData, connInfo.pScanConnInfo, connInfo.uScanInfoLen); ++ } ++ else ++ { ++ pDConnInfo->uScanConnInfoOffset = 0; ++ } ++ ++ ++ cmd->dataLen = sizeof(*pDConnInfo); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ DbgPrint("NwScanConnInfo: Reply recieved\n"); ++ DbgPrint(" NextIndex = %x\n", connInfo.uScanIndex); ++ DbgPrint(" ErrorCode = %x\n", reply->Reply.ErrorCode); ++ DbgPrint(" data = %x\n", reply->data); ++ ++ pDConnInfo = (PNwdCScanConnInfo)reply->data; ++ retCode = (u_long)reply->Reply.ErrorCode; ++ if (!retCode) ++ { ++ GetUserData(&connInfo, cmd, reply); ++ rInfo = (NwcScanConnInfo *)pdata->repData; ++ cpylen = copy_to_user(pdata->repData, &pDConnInfo->uScanIndex, sizeof(pDConnInfo->uScanIndex)); ++ cpylen = copy_to_user(&rInfo->uConnectionReference, &pDConnInfo->uConnectionReference, sizeof(pDConnInfo->uConnectionReference)); ++ } ++ else ++ { ++ u_long x; ++ ++ x = 0; ++ rInfo = (NwcScanConnInfo *)pdata->reqData; ++ cpylen = copy_to_user(&rInfo->uConnectionReference, &x, sizeof(rInfo->uConnectionReference)); ++ } ++ ++ Novfs_Free(reply); ++ } ++ else ++ { ++ retCode = -EIO; ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++void GetUserData(NwcScanConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply) ++/* ++ * Abstract: Copies the user data out of the scan conn info call. ++ * ++ *========================================================================*/ ++ ++{ ++u_long uLevel; ++PNwdCScanConnInfo pDConnInfo; ++ ++u_char *srcData = NULL; ++u_long dataLen = 0, cpylen; ++ ++ ++ pDConnInfo = (PNwdCScanConnInfo)reply->data; ++ uLevel = pDConnInfo->uReturnInfoLevel; ++ DbgPrint("[GetUserData] uLevel = %d, reply = 0x%X, reply->data = 0x%X\n", uLevel, reply, reply->data); ++ ++ switch(uLevel) ++ { ++ case NWC_CONN_INFO_RETURN_ALL: ++ case NWC_CONN_INFO_TRAN_ADDR: ++ case NWC_CONN_INFO_NDS_STATE: ++ case NWC_CONN_INFO_MAX_PACKET_SIZE: ++ case NWC_CONN_INFO_LICENSE_STATE: ++ case NWC_CONN_INFO_PUBLIC_STATE: ++ case NWC_CONN_INFO_SERVICE_TYPE: ++ case NWC_CONN_INFO_DISTANCE: ++ case NWC_CONN_INFO_SERVER_VERSION: ++ case NWC_CONN_INFO_AUTH_ID: ++ case NWC_CONN_INFO_SUSPENDED: ++ case NWC_CONN_INFO_WORKGROUP_ID: ++ case NWC_CONN_INFO_SECURITY_STATE: ++ case NWC_CONN_INFO_CONN_NUMBER: ++ case NWC_CONN_INFO_USER_ID: ++ case NWC_CONN_INFO_BCAST_STATE: ++ case NWC_CONN_INFO_CONN_REF: ++ case NWC_CONN_INFO_AUTH_STATE: ++ case NWC_CONN_INFO_TREE_NAME: ++ case NWC_CONN_INFO_SERVER_NAME: ++ case NWC_CONN_INFO_VERSION: ++ srcData = (u_char *)pDConnInfo; ++ srcData += pDConnInfo->uReturnConnInfoOffset; ++ dataLen = pDConnInfo->uReturnInfoLength; ++ break; ++ ++ case NWC_CONN_INFO_RETURN_NONE: ++ case NWC_CONN_INFO_TREE_NAME_UNICODE: ++ case NWC_CONN_INFO_SERVER_NAME_UNICODE: ++ case NWC_CONN_INFO_LOCAL_TRAN_ADDR: ++ case NWC_CONN_INFO_ALTERNATE_ADDR: ++ case NWC_CONN_INFO_SERVER_GUID: ++ default: ++ break; ++ } ++ ++ if (srcData && dataLen) ++ { ++ DbgPrint("Copy Data in GetUserData 0x%X -> 0x%X :: 0x%X\n", ++ srcData, connInfo->pReturnConnInfo, dataLen); ++ cpylen = copy_to_user(connInfo->pReturnConnInfo, srcData, dataLen); ++ } ++ ++ return; ++} ++ ++/*++======================================================================*/ ++void GetConnData(NwcGetConnInfo *connInfo, PXPLAT_CALL_REQUEST cmd, PXPLAT_CALL_REPLY reply) ++/* ++ * Abstract: Copies the user data out of the scan conn info call. ++ * ++ *========================================================================*/ ++ ++{ ++u_long uLevel; ++PNwdCGetConnInfo pDConnInfo; ++ ++u_char *srcData = NULL; ++u_long dataLen = 0, cpylen; ++ ++ ++ pDConnInfo = (PNwdCGetConnInfo)cmd->data; ++ uLevel = pDConnInfo->uInfoLevel; ++ ++ switch(uLevel) ++ { ++ case NWC_CONN_INFO_RETURN_ALL: ++ srcData = (u_char *)reply->data; ++ dataLen = reply->dataLen; ++ break; ++ ++ case NWC_CONN_INFO_RETURN_NONE: ++ dataLen = 0; ++ break; ++ ++ case NWC_CONN_INFO_TRAN_ADDR: ++ { ++ u_char *dstData = connInfo->pConnInfo; ++ NwcTranAddr tranAddr; ++ ++ srcData = (u_char *)reply->data; ++ ++ cpylen = copy_from_user(&tranAddr, dstData, sizeof(tranAddr)); ++ tranAddr.uTransportType = ((PNwdTranAddr)srcData)->uTransportType; ++ tranAddr.uAddressLength = ((PNwdTranAddr)srcData)->uAddressLength; ++ cpylen = copy_to_user(dstData, &tranAddr, sizeof(tranAddr)); ++ cpylen = copy_to_user(tranAddr.puAddress, ((PNwdTranAddr)srcData)->Buffer, ((PNwdTranAddr)srcData)->uAddressLength); ++ dataLen=0; ++ break; ++ } ++ case NWC_CONN_INFO_NDS_STATE: ++ case NWC_CONN_INFO_MAX_PACKET_SIZE: ++ case NWC_CONN_INFO_LICENSE_STATE: ++ case NWC_CONN_INFO_PUBLIC_STATE: ++ case NWC_CONN_INFO_SERVICE_TYPE: ++ case NWC_CONN_INFO_DISTANCE: ++ case NWC_CONN_INFO_SERVER_VERSION: ++ case NWC_CONN_INFO_AUTH_ID: ++ case NWC_CONN_INFO_SUSPENDED: ++ case NWC_CONN_INFO_WORKGROUP_ID: ++ case NWC_CONN_INFO_SECURITY_STATE: ++ case NWC_CONN_INFO_CONN_NUMBER: ++ case NWC_CONN_INFO_USER_ID: ++ case NWC_CONN_INFO_BCAST_STATE: ++ case NWC_CONN_INFO_CONN_REF: ++ case NWC_CONN_INFO_AUTH_STATE: ++ case NWC_CONN_INFO_VERSION: ++ case NWC_CONN_INFO_SERVER_NAME: ++ case NWC_CONN_INFO_TREE_NAME: ++ srcData = (u_char *)reply->data; ++ dataLen = reply->dataLen; ++ break; ++ ++ case NWC_CONN_INFO_TREE_NAME_UNICODE: ++ case NWC_CONN_INFO_SERVER_NAME_UNICODE: ++ break; ++ ++ case NWC_CONN_INFO_LOCAL_TRAN_ADDR: ++ break; ++ ++ case NWC_CONN_INFO_ALTERNATE_ADDR: ++ break; ++ ++ case NWC_CONN_INFO_SERVER_GUID: ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (srcData && dataLen) ++ { ++ cpylen = copy_to_user(connInfo->pConnInfo, srcData, connInfo->uInfoLength); ++ } ++ ++ return; ++} ++ ++/*++======================================================================*/ ++int NwGetDaemonVersion(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCGetRequesterVersion pDVersion; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ datalen = sizeof(*pDVersion); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_GET_REQUESTER_VERSION; ++ cmdlen = sizeof(*cmd); ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ pDVersion = (PNwdCGetRequesterVersion)reply->data; ++ cpylen = copy_to_user(pDVersion, pdata->reqData, sizeof(*pDVersion)); ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++ ++/*++======================================================================*/ ++int NwcGetPreferredDSTree(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCGetPreferredDsTree pDGetTree; ++NwcGetPreferredDsTree xplatCall, *p; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++u_char *dPtr; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcGetPreferredDsTree)); ++ datalen = sizeof(*pDGetTree) + xplatCall.uTreeLength; ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_GET_PREFERRED_DS_TREE; ++ cmdlen = sizeof(*cmd); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ if (!retCode) ++ { ++ pDGetTree = (PNwdCGetPreferredDsTree)reply->data; ++ dPtr = reply->data + pDGetTree->DsTreeNameOffset; ++ p = (NwcGetPreferredDsTree *)pdata->reqData; ++ ++ DbgPrint("NwcGetPreferredDSTree: Reply recieved\n"); ++ DbgPrint(" TreeLen = %x\n", pDGetTree->uTreeLength); ++ DbgPrint(" TreeName = %s\n", dPtr); ++ ++ cpylen = copy_to_user(p, &pDGetTree->uTreeLength, 4); ++ cpylen = copy_to_user(xplatCall.pDsTreeName, dPtr, pDGetTree->uTreeLength); ++ } ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwcSetPreferredDSTree(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++PNwdCSetPreferredDsTree pDSetTree; ++NwcSetPreferredDsTree xplatCall; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++u_char *dPtr; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetPreferredDsTree)); ++ datalen = sizeof(*pDSetTree) + xplatCall.uTreeLength; ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SET_PREFERRED_DS_TREE; ++ ++ pDSetTree = (PNwdCSetPreferredDsTree)cmd->data; ++ pDSetTree->DsTreeNameOffset = sizeof(*pDSetTree); ++ pDSetTree->uTreeLength = xplatCall.uTreeLength; ++ ++ dPtr = cmd->data + sizeof(*pDSetTree); ++ cpylen = copy_from_user(dPtr, xplatCall.pDsTreeName, xplatCall.uTreeLength); ++ ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++ ++/*++======================================================================*/ ++int NwcSetDefaultNameCtx(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcSetDefaultNameContext xplatCall; ++PNwdCSetDefaultNameContext pDSet; ++u_long retCode = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++u_char *dPtr; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetDefaultNameContext)); ++ datalen = sizeof(*pDSet) + xplatCall.uTreeLength + xplatCall.uNameLength; ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SET_DEFAULT_NAME_CONTEXT; ++ cmd->dataLen = sizeof(NwdCSetDefaultNameContext) + xplatCall.uTreeLength + xplatCall.uNameLength; ++ ++ pDSet = (PNwdCSetDefaultNameContext)cmd->data; ++ dPtr = cmd->data; ++ ++ pDSet->TreeOffset = sizeof(NwdCSetDefaultNameContext); ++ pDSet->uTreeLength = xplatCall.uTreeLength; ++ pDSet->NameContextOffset = pDSet->TreeOffset+xplatCall.uTreeLength; ++ pDSet->uNameLength = xplatCall.uNameLength; ++ ++ cpylen = copy_from_user(dPtr+pDSet->TreeOffset, xplatCall.pTreeName, xplatCall.uTreeLength); ++ cpylen = copy_from_user(dPtr+pDSet->NameContextOffset, xplatCall.pNameContext, xplatCall.uNameLength); ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwcGetDefaultNameCtx(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcGetDefaultNameContext xplatCall; ++PNwdCGetDefaultNameContext pGet; ++char *dPtr; ++int retCode = -ENOMEM; ++u_long cmdlen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcGetDefaultNameContext)); ++ cmdlen = sizeof(*cmd) + sizeof(NwdCGetDefaultNameContext) + xplatCall.uTreeLength; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_GET_DEFAULT_NAME_CONTEXT; ++ cmd->dataLen = sizeof(NwdCGetDefaultNameContext)+xplatCall.uTreeLength; ++ ++ pGet = (PNwdCGetDefaultNameContext)cmd->data; ++ dPtr = cmd->data; ++ ++ pGet->TreeOffset = sizeof(NwdCGetDefaultNameContext); ++ pGet->uTreeLength = xplatCall.uTreeLength; ++ ++ cpylen = copy_from_user( dPtr + pGet->TreeOffset, xplatCall.pTreeName, xplatCall.uTreeLength); ++ dPtr[pGet->TreeOffset+pGet->uTreeLength] = 0; ++ ++ retCode = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ retCode = reply->Reply.ErrorCode; ++ if (!retCode) ++ { ++ pGet = (PNwdCGetDefaultNameContext)reply->data; ++ ++ DbgPrint("NwcGetDefaultNameCtx: retCode=0x%x uNameLength1=%d uNameLength2=%d\n", retCode, pGet->uNameLength, xplatCall.uNameLength); ++ if (xplatCall.uNameLength < pGet->uNameLength) ++ { ++ pGet->uNameLength = xplatCall.uNameLength; ++ retCode = NWE_BUFFER_OVERFLOW; ++ } ++ dPtr = (char *)pGet + pGet->NameContextOffset; ++ cpylen = copy_to_user(xplatCall.pNameContext, dPtr, pGet->uNameLength); ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(retCode); ++ ++} ++ ++/*++======================================================================*/ ++int NwQueryFeature(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ NwcQueryFeature xpCall; ++ int status = SUCCESS; ++ u_long cpylen; ++ ++ cpylen = copy_from_user(&xpCall, pdata->reqData, sizeof(NwcQueryFeature)); ++ switch (xpCall.Feature) ++ { ++ case NWC_FEAT_NDS: ++ case NWC_FEAT_NDS_MTREE: ++ case NWC_FEAT_PRN_CAPTURE: ++ case NWC_FEAT_NDS_RESOLVE: ++ ++ status = NWE_REQUESTER_FAILURE; ++ ++ } ++ return( status ); ++} ++ ++/*++======================================================================*/ ++int NwcGetTreeMonitoredConn(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcGetTreeMonitoredConnRef xplatCall, *p; ++PNwdCGetTreeMonitoredConnRef pDConnRef; ++char *dPtr; ++u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcGetTreeMonitoredConnRef)); ++ datalen = sizeof(*pDConnRef) + xplatCall.pTreeName->DataLen; ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_GET_TREE_MONITORED_CONN_REF; ++ ++ pDConnRef = (PNwdCGetTreeMonitoredConnRef)cmd->data; ++ pDConnRef->TreeName.boffset = sizeof(*pDConnRef); ++ pDConnRef->TreeName.len = xplatCall.pTreeName->DataLen; ++ pDConnRef->TreeName.type = xplatCall.pTreeName->DataType; ++ ++ dPtr = cmd->data + sizeof(*pDConnRef); ++ cpylen = copy_from_user(dPtr, xplatCall.pTreeName->pBuffer, pDConnRef->TreeName.len); ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ pDConnRef = (PNwdCGetTreeMonitoredConnRef)reply->data; ++ dPtr = reply->data + pDConnRef->TreeName.boffset; ++ p = (NwcGetTreeMonitoredConnRef *)pdata->reqData; ++ cpylen = copy_to_user(&p->uConnReference, &pDConnRef->uConnReference, 4); ++ ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ ++ } ++ ++ return(status); ++} ++ ++/*++======================================================================*/ ++int NwcEnumIdentities(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcEnumerateIdentities xplatCall, *eId; ++PNwdCEnumerateIdentities pEnum; ++NwcString xferStr; ++char *str; ++u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcEnumerateIdentities)); ++ datalen = sizeof(*pEnum); ++ cmdlen = datalen + sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_ENUMERATE_IDENTITIES; ++ ++ DbgPrint("NwcEnumIdentities: Send Request\n"); ++ DbgPrint(" iterator = %x\n", xplatCall.Iterator); ++ DbgPrint(" cmdlen = %d\n", cmdlen); ++ ++ pEnum = (PNwdCEnumerateIdentities)cmd->data; ++ pEnum->Iterator = xplatCall.Iterator; ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ ++ eId = pdata->repData; ++ pEnum = (PNwdCEnumerateIdentities)reply->data; ++ cpylen = copy_to_user(&eId->Iterator, &pEnum->Iterator, sizeof(pEnum->Iterator)); ++ DbgPrint("[XPLAT NWCAPI] Found AuthId 0x%X\n", pEnum->AuthenticationId); ++ cpylen = copy_to_user(&eId->AuthenticationId, &pEnum->AuthenticationId, sizeof(pEnum->AuthenticationId)); ++ cpylen = copy_to_user(&eId->AuthType, &pEnum->AuthType, sizeof(pEnum->AuthType)); ++ cpylen = copy_to_user(&eId->IdentityFlags, &pEnum->IdentityFlags, sizeof(pEnum->IdentityFlags)); ++ cpylen = copy_to_user(&eId->NameType, &pEnum->NameType, sizeof(pEnum->NameType)); ++ cpylen = copy_to_user(&eId->ObjectType, &pEnum->ObjectType, sizeof(pEnum->ObjectType)); ++ ++ if (!status) ++ { ++ cpylen = copy_from_user(&xferStr, eId->pDomainName, sizeof(NwcString)); ++ str = (char *)((char *)reply->data + pEnum->domainNameOffset); ++ DbgPrint("[XPLAT NWCAPI] Found Domain %s\n", str); ++ cpylen = copy_to_user(xferStr.pBuffer, str, pEnum->domainNameLen); ++ xferStr.DataType = NWC_STRING_TYPE_ASCII; ++ xferStr.DataLen = pEnum->domainNameLen - 1; ++ cpylen = copy_to_user(eId->pDomainName, &xferStr, sizeof(NwcString)); ++ ++ ++ cpylen = copy_from_user(&xferStr, eId->pObjectName, sizeof(NwcString)); ++ str = (char *)((char *)reply->data + pEnum->objectNameOffset); ++ DbgPrint("[XPLAT NWCAPI] Found User %s\n", str); ++ cpylen = copy_to_user(xferStr.pBuffer, str, pEnum->objectNameLen); ++ xferStr.DataType = NWC_STRING_TYPE_ASCII; ++ xferStr.DataLen = pEnum->objectNameLen - 1; ++ cpylen = copy_to_user(eId->pObjectName, &xferStr, sizeof(NwcString)); ++ } ++ ++ Novfs_Free(reply); ++ ++ } ++ Novfs_Free(cmd); ++ ++ } ++ return(status); ++} ++ ++/*++======================================================================*/ ++int NwcChangeAuthKey(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Change the password on the server ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcChangeKey xplatCall; ++PNwdCChangeKey pNewKey; ++NwcString xferStr; ++char *str; ++u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcChangeKey)); ++ ++ datalen = sizeof(NwdCChangeKey) + xplatCall.pDomainName->DataLen + xplatCall.pObjectName->DataLen ++ + xplatCall.pNewPassword->DataLen + xplatCall.pVerifyPassword->DataLen; ++ ++ cmdlen = sizeof(*cmd) + datalen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ pNewKey = (PNwdCChangeKey)cmd->data; ++ cmd->dataLen = datalen; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_CHANGE_KEY; ++ ++ pNewKey->NameType = xplatCall.NameType; ++ pNewKey->ObjectType = xplatCall.ObjectType; ++ pNewKey->AuthType = xplatCall.AuthType; ++ str = (char *)pNewKey; ++ ++ /* ++ * Get the tree name ++ */ ++ str += sizeof(*pNewKey); ++ cpylen = copy_from_user(&xferStr, xplatCall.pDomainName, sizeof(NwcString)); ++ pNewKey->domainNameOffset = sizeof(*pNewKey); ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->domainNameLen = xferStr.DataLen; ++ ++ /* ++ * Get the User Name ++ */ ++ str += pNewKey->domainNameLen; ++ cpylen = copy_from_user(&xferStr, xplatCall.pObjectName, sizeof(NwcString)); ++ pNewKey->objectNameOffset = pNewKey->domainNameOffset + pNewKey->domainNameLen; ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->objectNameLen = xferStr.DataLen; ++ ++ /* ++ * Get the New Password ++ */ ++ str += pNewKey->objectNameLen; ++ cpylen = copy_from_user(&xferStr, xplatCall.pNewPassword, sizeof(NwcString)); ++ pNewKey->newPasswordOffset = pNewKey->objectNameOffset + pNewKey->objectNameLen; ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->newPasswordLen = xferStr.DataLen; ++ ++ /* ++ * Get the Verify Password ++ */ ++ str += pNewKey->newPasswordLen; ++ cpylen = copy_from_user(&xferStr, xplatCall.pVerifyPassword, sizeof(NwcString)); ++ pNewKey->verifyPasswordOffset = pNewKey->newPasswordOffset + pNewKey->newPasswordLen; ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->verifyPasswordLen = xferStr.DataLen; ++ ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ memset(cmd, 0, cmdlen); ++ ++ Novfs_Free(cmd); ++ } ++ ++ return(status); ++} ++ ++/*++======================================================================*/ ++int NwcSetPrimaryConn(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Set the primary connection Id ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcSetPrimaryConnection xplatCall; ++PNwdCSetPrimaryConnection pConn; ++u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetPrimaryConnection)); ++ ++ datalen = sizeof(NwdCSetPrimaryConnection); ++ cmdlen = sizeof(*cmd) + datalen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ pConn = (PNwdCSetPrimaryConnection)cmd->data; ++ cmd->dataLen = datalen; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SET_PRIMARY_CONN; ++ pConn->ConnHandle = xplatCall.ConnHandle; ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ ++ Novfs_Free(cmd); ++ } ++ ++ return(status); ++} ++ ++/*++======================================================================*/ ++int NwcGetPrimaryConn(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Get the Primary connection ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++XPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long status = -ENOMEM, cmdlen, replylen, cpylen; ++ ++ ++ cmdlen = (u_long)(&((PXPLAT_CALL_REQUEST)0)->data); ++ ++ cmd.dataLen = 0; ++ cmd.Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd.Command.SequenceNumber = 0; ++ cmd.Command.SessionId = Session; ++ cmd.NwcCommand = NWC_GET_PRIMARY_CONN; ++ ++ status = Queue_Daemon_Command((void *)&cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ if (!status) ++ { ++ cpylen = copy_to_user(pdata->repData, reply->data, sizeof(u_long)); ++ } ++ ++ Novfs_Free(reply); ++ } ++ ++ return(status); ++} ++ ++ ++/*++======================================================================*/ ++int NwcSetMapDrive(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Get the Primary connection ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long status = 0, datalen, cmdlen, replylen, cpylen; ++NwcMapDriveEx symInfo; ++ ++ DbgPrint("Call to NwcSetMapDrive\n"); ++ cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); ++ cmdlen = sizeof(*cmd); ++ datalen = sizeof(symInfo) + symInfo.dirPathOffsetLength + symInfo.linkOffsetLength; ++ ++ DbgPrint(" cmdlen = %d\n", cmdlen); ++ DbgPrint(" dataLen = %d\n", datalen); ++ DbgPrint(" symInfo.dirPathOffsetLength = %d\n", symInfo.dirPathOffsetLength); ++ DbgPrint(" symInfo.linkOffsetLength = %d\n", symInfo.linkOffsetLength); ++ DbgPrint(" pdata->datalen = %d\n", pdata->reqLen); ++ ++ mydump(sizeof(symInfo), &symInfo); ++ ++ cmdlen += datalen; ++ ++ ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->dataLen = datalen; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_MAP_DRIVE; ++ ++ cpylen = copy_from_user(cmd->data, pdata->reqData, datalen); ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(status); ++ ++} ++ ++/*++======================================================================*/ ++int NwcUnMapDrive(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Get the Primary connection ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long status = 0, datalen, cmdlen, replylen, cpylen; ++NwcUnmapDriveEx symInfo; ++ ++ DbgPrint("Call to NwcUnMapDrive\n"); ++ ++ cpylen = copy_from_user(&symInfo, pdata->reqData, sizeof(symInfo)); ++ cmdlen = sizeof(*cmd); ++ datalen = sizeof(symInfo) + symInfo.linkLen; ++ ++ cmdlen += datalen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->dataLen = datalen; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_UNMAP_DRIVE; ++ ++ cpylen = copy_from_user(cmd->data, pdata->reqData, datalen); ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ ++ return(status); ++} ++ ++ ++/*++======================================================================*/ ++int NwcEnumerateDrives(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Get the Primary connection ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long status = 0, cmdlen, replylen, cpylen; ++u_long offset; ++char *cp; ++ ++ DbgPrint("Call to NwcEnumerateDrives\n"); ++ ++ cmdlen = sizeof(*cmd); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ cmd->dataLen = 0; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_ENUMERATE_DRIVES; ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ DbgPrint("Status Code = 0x%X\n", status); ++ if (!status) ++ { ++ offset = sizeof(u_long); ++ cp = reply->data; ++ replylen = ((PNwcGetMappedDrives)pdata->repData)->MapBuffLen; ++ cpylen = copy_to_user(pdata->repData, cp, offset); ++ cp += offset; ++ cpylen = copy_to_user(((PNwcGetMappedDrives)pdata->repData)->MapBuffer, cp, min(replylen - offset, reply->dataLen - offset)); ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ ++ return(status); ++} ++ ++ ++/*++======================================================================*/ ++int NwcGetBroadcastMessage(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Get the Primary connection ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++u_long status = 0x8866, cmdlen, replylen, cpylen; ++NwcGetBroadcastNotification msg; ++PNwdCGetBroadcastNotification dmsg; ++ ++ cmdlen = sizeof(*cmd) + sizeof(*dmsg); ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ if (cmd) ++ { ++ ++ cpylen = copy_from_user(&msg, pdata->reqData, sizeof(msg)); ++ cmd->dataLen = sizeof(*dmsg); ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ ++ cmd->NwcCommand = NWC_GET_BROADCAST_MESSAGE; ++ dmsg = (PNwdCGetBroadcastNotification)cmd->data; ++ dmsg->uConnReference = msg.uConnReference; ++ ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ DbgPrint("Status Code = 0x%X\n", status); ++ if (!status) ++ { ++ /* we have a message so copy it to the user buffer */ ++ cpylen = copy_to_user(pdata->repData, reply->data, min(pdata->repLen, reply->dataLen)); ++ } ++ else ++ { ++ msg.messageLen = 0; ++ msg.message[0] = 0; ++ cpylen = copy_to_user(pdata->repData, &msg, sizeof(msg)); ++ } ++ ++ Novfs_Free(reply); ++ } ++ Novfs_Free(cmd); ++ } ++ return(status); ++ ++} ++ ++ ++int NwdSetKeyValue(PXPLAT pdata, session_t Session) ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcSetKey xplatCall; ++PNwdCSetKey pNewKey; ++NwcString cstrObjectName, cstrPassword; ++char *str; ++u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcSetKey)); ++ cpylen = copy_from_user(&cstrObjectName, xplatCall.pObjectName, sizeof(NwcString)); ++ cpylen = copy_from_user(&cstrPassword, xplatCall.pNewPassword, sizeof(NwcString)); ++ ++ datalen = sizeof(NwdCSetKey) + cstrObjectName.DataLen + cstrPassword.DataLen; ++ ++ cmdlen = sizeof(*cmd) + datalen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ pNewKey = (PNwdCSetKey)cmd->data; ++ cmd->dataLen = datalen; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_SET_KEY; ++ ++ pNewKey->ObjectType = xplatCall.ObjectType; ++ pNewKey->AuthenticationId = xplatCall.AuthenticationId; ++ pNewKey->ConnHandle = xplatCall.ConnHandle; ++ str = (char *)pNewKey; ++ ++ /* ++ * Get the User Name ++ */ ++ str += sizeof(NwdCSetKey); ++ cpylen = copy_from_user(str, cstrObjectName.pBuffer, cstrObjectName.DataLen); ++ ++ str += ++ pNewKey->objectNameLen = cstrObjectName.DataLen; ++ pNewKey->objectNameOffset = sizeof(NwdCSetKey); ++ ++ /* ++ * Get the Verify Password ++ */ ++ cpylen = copy_from_user(str, cstrPassword.pBuffer, cstrPassword.DataLen); ++ ++ pNewKey->newPasswordLen = cstrPassword.DataLen; ++ pNewKey->newPasswordOffset = pNewKey->objectNameOffset+pNewKey->objectNameLen; ++ ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ memset(cmd, 0, cmdlen); ++ Novfs_Free(cmd); ++ } ++ ++ return(status); ++} ++ ++/*++======================================================================*/ ++int NwdVerifyKeyValue(PXPLAT pdata, session_t Session) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: Change the password on the server ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++PXPLAT_CALL_REQUEST cmd; ++PXPLAT_CALL_REPLY reply; ++NwcVerifyKey xplatCall; ++PNwdCVerifyKey pNewKey; ++NwcString xferStr; ++char *str; ++u_long status = -ENOMEM, cmdlen, datalen, replylen, cpylen; ++ ++ cpylen = copy_from_user(&xplatCall, pdata->reqData, sizeof(NwcVerifyKey)); ++ ++ datalen = sizeof(NwdCVerifyKey) + xplatCall.pDomainName->DataLen + xplatCall.pObjectName->DataLen ++ + xplatCall.pVerifyPassword->DataLen; ++ ++ cmdlen = sizeof(*cmd) + datalen; ++ cmd = Novfs_Malloc(cmdlen, GFP_KERNEL); ++ ++ if (cmd) ++ { ++ pNewKey = (PNwdCVerifyKey)cmd->data; ++ cmd->dataLen = datalen; ++ cmd->Command.CommandType = VFS_COMMAND_XPLAT_CALL; ++ cmd->Command.SequenceNumber = 0; ++ cmd->Command.SessionId = Session; ++ cmd->NwcCommand = NWC_VERIFY_KEY; ++ ++ pNewKey->NameType = xplatCall.NameType; ++ pNewKey->ObjectType = xplatCall.ObjectType; ++ pNewKey->AuthType = xplatCall.AuthType; ++ str = (char *)pNewKey; ++ ++ /* ++ * Get the tree name ++ */ ++ str += sizeof(*pNewKey); ++ cpylen = copy_from_user(&xferStr, xplatCall.pDomainName, sizeof(NwcString)); ++ pNewKey->domainNameOffset = sizeof(*pNewKey); ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->domainNameLen = xferStr.DataLen; ++ ++ /* ++ * Get the User Name ++ */ ++ str += pNewKey->domainNameLen; ++ cpylen = copy_from_user(&xferStr, xplatCall.pObjectName, sizeof(NwcString)); ++ pNewKey->objectNameOffset = pNewKey->domainNameOffset + pNewKey->domainNameLen; ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->objectNameLen = xferStr.DataLen; ++ ++ /* ++ * Get the Verify Password ++ */ ++ str += pNewKey->objectNameLen; ++ cpylen = copy_from_user(&xferStr, xplatCall.pVerifyPassword, sizeof(NwcString)); ++ pNewKey->verifyPasswordOffset = pNewKey->objectNameOffset + pNewKey->objectNameLen; ++ cpylen = copy_from_user(str, xferStr.pBuffer, xferStr.DataLen); ++ pNewKey->verifyPasswordLen = xferStr.DataLen; ++ ++ status = Queue_Daemon_Command((void *)cmd, cmdlen, NULL, 0, (void **)&reply, &replylen, INTERRUPTIBLE); ++ if (reply) ++ { ++ status = reply->Reply.ErrorCode; ++ Novfs_Free(reply); ++ } ++ memset(cmd, 0, cmdlen); ++ Novfs_Free(cmd); ++ } ++ ++ return(status); ++} +diff -uNr src.old/src/proc.c src/src/proc.c +--- src.old/src/proc.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/proc.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,339 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: proc.c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module contains functions that create the ++ * interface to the proc filesystem. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#include ++#include ++#include ++#include ++ ++/*===[ Include files specific to this module ]============================*/ ++#include "vfs.h" ++ ++/*===[ External data ]====================================================*/ ++extern char *Novfs_CurrentMount; ++ ++/*===[ External prototypes ]==============================================*/ ++extern int DbgPrint( char *Fmt, ... ); ++ ++extern ssize_t ++Daemon_Receive_Reply(struct file *file, const char *buf, size_t nbytes, loff_t *ppos); ++ ++extern ssize_t ++Daemon_Send_Command(struct file *file, char *buf, size_t len, loff_t *off); ++ ++extern int Daemon_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++ ++extern int Daemon_Library_close(struct inode *inode, struct file *file); ++extern int Daemon_Library_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++extern int Daemon_Library_open(struct inode *inode, struct file *file); ++extern ssize_t Daemon_Library_read(struct file *file, char *buf, size_t len, loff_t *off); ++extern ssize_t Daemon_Library_write(struct file *file, const char *buf, size_t len, loff_t *off); ++extern loff_t Daemon_Library_llseek(struct file *file, loff_t offset, int origin); ++ ++extern int Daemon_Open_Control(struct inode *Inode, struct file *File); ++extern int Daemon_Close_Control(struct inode *Inode, struct file *File); ++ ++extern int Daemon_getversion( char *Buf, int Length ); ++ ++/*===[ Manifest constants ]===============================================*/ ++ ++/*===[ Type definitions ]=================================================*/ ++ ++/*===[ Function prototypes ]==============================================*/ ++ssize_t ++Novfs_User_proc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos); ++ ++ssize_t ++Novfs_User_proc_write(struct file * file, char * buf, size_t nbytes, loff_t *ppos); ++ ++int Novfs_User_proc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++ ++int Init_Procfs_Interface( void ); ++void Uninit_Procfs_Interface( void ); ++ ++/*===[ Global variables ]=================================================*/ ++struct proc_dir_entry *Novfs_Procfs_dir, *Novfs_Control, *Novfs_Library, *Novfs_Version; ++static struct file_operations Daemon_proc_fops; ++static struct file_operations Library_proc_fops; ++ ++/*===[ Code ]=============================================================*/ ++ ++/*++======================================================================*/ ++int Novfs_Get_Version(char *page, char **start, off_t off, int count, int *eof, void *data) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *buf, tbuf[48]; ++ int len=0, i; ++ ++ if ( !off ) ++ { ++ buf = page+off; ++ *start = buf; ++ len = sprintf(buf, "Novfs Version=%s\n", NOVFS_VERSION_STRING); ++ i = Daemon_getversion(tbuf, sizeof(tbuf)); ++ if ((i > 0) && i < (count-len)) ++ { ++ len += sprintf(buf+len, "Novfsd Version=%s\n", tbuf); ++ } ++ ++ if (Novfs_CurrentMount) ++ { ++ i = strlen(Novfs_CurrentMount); ++ if ((i > 0) && i < (count-len)) ++ { ++ len += sprintf(buf+len, "Novfs mount=%s\n", Novfs_CurrentMount); ++ } ++ } ++ DbgPrint("Novfs_Get_Version:\n%s\n", buf); ++ } ++ *eof = 1; ++ return(len); ++} ++ ++/*++======================================================================*/ ++ssize_t ++Novfs_User_proc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ssize_t retval=0; ++ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(buf); ++ UNUSED_VARIABLE(nbytes); ++ UNUSED_VARIABLE(ppos); ++ ++ DbgPrint( "Novfs_User_proc_read: kernel_locked 0x%x\n", kernel_locked()); ++ ++ return retval; ++} ++/*++======================================================================*/ ++ssize_t ++Novfs_User_proc_write(struct file * file, char * buf, size_t nbytes, loff_t *ppos) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ssize_t retval=0; ++ ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(ppos); ++ ++ DbgPrint( "Novfs_User_proc_write: kernel_locked 0x%x\n", kernel_locked()); ++ if (buf && nbytes) ++ { ++ } ++ ++ return(retval); ++} ++ ++/*++======================================================================*/ ++int Novfs_User_proc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retval=-ENOSYS; ++ ++ UNUSED_VARIABLE(inode); ++ UNUSED_VARIABLE(file); ++ UNUSED_VARIABLE(cmd); ++ UNUSED_VARIABLE(arg); ++ ++ DbgPrint( "Novfs_User_proc_ioctl: kernel_locked 0x%x\n", kernel_locked()); ++ ++ return(retval); ++} ++ ++/*++======================================================================*/ ++int Init_Procfs_Interface( void ) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ int retCode=0; ++ ++ Novfs_Procfs_dir = proc_mkdir(MODULE_NAME, NULL); ++ if ( Novfs_Procfs_dir ) ++ { ++ Novfs_Procfs_dir->owner = THIS_MODULE; ++ ++ Novfs_Control = create_proc_entry("Control", 0600, Novfs_Procfs_dir); ++ ++ if ( Novfs_Control ) ++ { ++ Novfs_Control->owner = THIS_MODULE; ++ Novfs_Control->size = 0; ++ memcpy(&Daemon_proc_fops, Novfs_Control->proc_fops, sizeof(struct file_operations)); ++ ++ /* ++ * Setup our functions ++ */ ++ Daemon_proc_fops.owner = THIS_MODULE; ++ Daemon_proc_fops.open = Daemon_Open_Control; ++ Daemon_proc_fops.release = Daemon_Close_Control; ++ Daemon_proc_fops.read = Daemon_Send_Command; ++ Daemon_proc_fops.write = Daemon_Receive_Reply; ++ Daemon_proc_fops.ioctl = Daemon_ioctl; ++ ++ Novfs_Control->proc_fops = &Daemon_proc_fops; ++ } ++ else ++ { ++ remove_proc_entry(MODULE_NAME, NULL); ++ return(-ENOENT); ++ } ++ ++ Novfs_Library = create_proc_entry("Library", 0666, Novfs_Procfs_dir); ++ if ( Novfs_Library ) ++ { ++ Novfs_Library->owner = THIS_MODULE; ++ Novfs_Library->size = 0; ++ ++ /* ++ * Setup our file functions ++ */ ++ memcpy(&Library_proc_fops, Novfs_Library->proc_fops, sizeof(struct file_operations)); ++ Library_proc_fops.owner = THIS_MODULE; ++ Library_proc_fops.open = Daemon_Library_open; ++ Library_proc_fops.release = Daemon_Library_close; ++ Library_proc_fops.read = Daemon_Library_read; ++ Library_proc_fops.write = Daemon_Library_write; ++ Library_proc_fops.llseek = Daemon_Library_llseek; ++ Library_proc_fops.ioctl = Daemon_Library_ioctl; ++ Novfs_Library->proc_fops = &Library_proc_fops; ++ } ++ else ++ { ++ remove_proc_entry("Control", Novfs_Procfs_dir); ++ remove_proc_entry(MODULE_NAME, NULL); ++ return(-ENOENT); ++ } ++ ++ Novfs_Version = create_proc_read_entry("Version", 0444, Novfs_Procfs_dir, Novfs_Get_Version, NULL); ++ if ( Novfs_Version ) ++ { ++ Novfs_Version->owner = THIS_MODULE; ++ Novfs_Version->size = 0; ++ } ++ else ++ { ++ remove_proc_entry("Library", Novfs_Procfs_dir); ++ remove_proc_entry("Control", Novfs_Procfs_dir); ++ remove_proc_entry(MODULE_NAME, NULL); ++ retCode = -ENOENT; ++ } ++ } ++ else ++ { ++ retCode = -ENOENT; ++ } ++ return(retCode); ++} ++ ++/*++======================================================================*/ ++void Uninit_Procfs_Interface( void ) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ ++ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Version, NULL)\n"); ++ remove_proc_entry("Version", Novfs_Procfs_dir); ++ ++ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Control, NULL)\n"); ++ remove_proc_entry("Control", Novfs_Procfs_dir); ++ ++ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(Library, NULL)\n"); ++ remove_proc_entry("Library", Novfs_Procfs_dir); ++ ++ DbgPrint("Uninit_Procfs_Interface remove_proc_entry(%s, NULL)\n", MODULE_NAME); ++ remove_proc_entry(MODULE_NAME, NULL); ++ ++ DbgPrint("Uninit_Procfs_Interface done\n"); ++} +diff -uNr src.old/src/profile.c src/src/profile.c +--- src.old/src/profile.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/profile.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,1199 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: profile.c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module contains a debugging code for ++ * the novfs VFS. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/*===[ Include files specific to this module ]============================*/ ++#include "vfs.h" ++ ++/*===[ External data ]====================================================*/ ++extern struct dentry *Novfs_root; ++extern struct proc_dir_entry *Novfs_Procfs_dir; ++extern unsigned long File_update_timeout; ++extern int PageCache; ++ ++/*===[ External prototypes ]==============================================*/ ++extern void Scope_Dump_Tasklist( void ); ++extern void Scope_Dump_Scopetable( void ); ++extern void Daemon_Dumpque( void ); ++extern char *Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags); ++extern int Novfs_dump_inode_cache(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++extern void Novfs_dump_inode( void *pf ); ++extern int Daemon_SendDebugCmd ( char *Command ); ++ ++ ++/*===[ Manifest constants ]===============================================*/ ++#define DBGBUFFERSIZE (1024*1024*32) ++ ++/*===[ Type definitions ]=================================================*/ ++typedef void daemon_command_t; ++ ++typedef struct _SYMBOL_TABLE { ++ void *address; ++ char *name; ++} SYMBOL_TABLE, *PSYMBOL_TABLE; ++ ++struct local_rtc_time { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++}; ++ ++/*===[ Function prototypes ]==============================================*/ ++int profile_task_exit_callback(struct notifier_block *self, unsigned long val, void *data) __attribute__((__no_instrument_function__)); ++int init_profile( void ); ++ ++char *ctime_r(time_t *clock, char *buf); ++int LocalPrint( char *Fmt, ... ) __attribute__((__no_instrument_function__)); ++int DbgPrint( char *Fmt, ... ) __attribute__((__no_instrument_function__)); ++ ++void __cyg_profile_func_enter (void *this_fn, void *call_site) __attribute__((__no_instrument_function__)) ; ++void __cyg_profile_func_exit (void *this_fn, void *call_site) __attribute__((__no_instrument_function__)); ++void doline(unsigned char *b, unsigned char *p, unsigned char *l) __attribute__((__no_instrument_function__)); ++void mydump(int size, void *dumpptr) __attribute__((__no_instrument_function__)); ++void GregorianDay(struct local_rtc_time * tm) __attribute__((__no_instrument_function__)); ++void to_tm(int tim, struct local_rtc_time * tm) __attribute__((__no_instrument_function__)); ++char *ctime_r(time_t *clock, char *buf) __attribute__((__no_instrument_function__)); ++int profile_dump_tasklist(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++int profile_dump_scopetable(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++int profile_dump_daemonque(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++int profile_dump_DbgBuffer(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++int profile_dump_DentryTree(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++int profile_dump_inode(int argc, const char **argv, const char **envp, struct pt_regs *regs); ++ ++void *Novfs_Malloc( size_t size, int flags ) __attribute__((__no_instrument_function__)); ++void Novfs_Free( const void *p ) __attribute__((__no_instrument_function__)); ++ ++int profile_dump_memorylist_dbg(int argc, const char **argv, const char **envp, struct pt_regs *regs) __attribute__((__no_instrument_function__)); ++void profile_dump_memorylist( void *pf ); ++ ++static ssize_t User_proc_write_DbgBuffer(struct file * file, const char __user *buf, size_t nbytes, loff_t *ppos) __attribute__((__no_instrument_function__)); ++static ssize_t User_proc_read_DbgBuffer(struct file * file, char * buf, size_t nbytes, loff_t *ppos) __attribute__((__no_instrument_function__)); ++static int proc_read_DbgBuffer(char *page, char **start, ++ off_t off, int count, ++ int *eof, void *data) __attribute__((__no_instrument_function__)); ++ ++void profile_dump_dt(struct dentry *parent, void *pf ); ++ssize_t profile_inode_read(struct file *file, char *buf, size_t len, loff_t *off); ++ssize_t profile_dentry_read(struct file *file, char *buf, size_t len, loff_t *off); ++ssize_t profile_memory_read(struct file *file, char *buf, size_t len, loff_t *off); ++uint64_t get_nanosecond_time( void ); ++ ++/*===[ Global variables ]=================================================*/ ++char *DbgPrintBuffer=NULL; ++char DbgPrintOn=0; ++char DbgSyslogOn=0; ++unsigned long DbgPrintBufferOffset=0; ++unsigned long DbgPrintBufferReadOffset=0; ++unsigned long DbgPrintBufferSize = DBGBUFFERSIZE; ++ ++int Indent = 0; ++char IndentString[] = " "; ++ ++static struct file_operations Dbg_proc_file_operations; ++static struct file_operations dentry_proc_file_ops; ++static struct file_operations inode_proc_file_ops; ++static struct file_operations memory_proc_file_ops; ++ ++static struct proc_dir_entry *dbg_dir=NULL, *dbg_file=NULL; ++static struct proc_dir_entry *dentry_file=NULL; ++static struct proc_dir_entry *inode_file=NULL; ++static struct proc_dir_entry *memory_file=NULL; ++ ++static struct notifier_block taskexit_nb; ++ ++ ++DECLARE_MUTEX(LocalPrint_lock); ++spinlock_t Syslog_lock = SPIN_LOCK_UNLOCKED; ++ ++#include "profile_funcs.h" ++ ++ ++/*===[ Code ]=============================================================*/ ++int ++profile_task_exit_callback(struct notifier_block *self, unsigned long val, void *data) ++{ ++ struct task_struct *task = (struct task_struct *)data; ++ ++ DbgPrint("profile_task_exit_callback: task 0x%p %u exiting %s\n", task, task->pid, task->comm); ++ return(0); ++} ++ ++int init_profile( void ) ++{ ++ int retCode = 0; ++ ++ if (Novfs_Procfs_dir) ++ { ++ dbg_dir = Novfs_Procfs_dir; ++ } ++ else ++ { ++ dbg_dir = proc_mkdir(MODULE_NAME, NULL); ++ } ++ ++ if( dbg_dir ) ++ { ++ dbg_dir->owner = THIS_MODULE; ++ dbg_file = create_proc_read_entry("Debug", ++ 0600, ++ dbg_dir, ++ proc_read_DbgBuffer, ++ NULL); ++ if ( dbg_file ) ++ { ++ dbg_file->owner = THIS_MODULE; ++ dbg_file->size = DBGBUFFERSIZE; ++ memcpy(&Dbg_proc_file_operations, dbg_file->proc_fops, sizeof(struct file_operations)); ++ Dbg_proc_file_operations.read = User_proc_read_DbgBuffer; ++ Dbg_proc_file_operations.write = User_proc_write_DbgBuffer; ++ dbg_file->proc_fops = &Dbg_proc_file_operations; ++ } ++ else ++ { ++ remove_proc_entry(MODULE_NAME, NULL); ++ vfree( DbgPrintBuffer ); ++ DbgPrintBuffer = NULL; ++ } ++ } ++ ++ if ( DbgPrintBuffer ) ++ { ++ if( dbg_dir ) ++ { ++ inode_file = create_proc_entry("inode", ++ 0600, ++ dbg_dir); ++ if ( inode_file ) ++ { ++ inode_file->owner = THIS_MODULE; ++ inode_file->size = 0; ++ memcpy(&inode_proc_file_ops, inode_file->proc_fops, sizeof(struct file_operations)); ++ inode_proc_file_ops.owner = THIS_MODULE; ++ inode_proc_file_ops.read = profile_inode_read; ++ inode_file->proc_fops = &inode_proc_file_ops; ++ } ++ ++ dentry_file = create_proc_entry("dentry", ++ 0600, ++ dbg_dir); ++ if ( dentry_file ) ++ { ++ dentry_file->owner = THIS_MODULE; ++ dentry_file->size = 0; ++ memcpy(&dentry_proc_file_ops, dentry_file->proc_fops, sizeof(struct file_operations)); ++ dentry_proc_file_ops.owner = THIS_MODULE; ++ dentry_proc_file_ops.read = profile_dentry_read; ++ dentry_file->proc_fops = &dentry_proc_file_ops; ++ } ++ ++ memory_file = create_proc_entry("memory", ++ 0600, ++ dbg_dir); ++ if ( memory_file ) ++ { ++ memory_file->owner = THIS_MODULE; ++ memory_file->size = 0; ++ memcpy(&memory_proc_file_ops, memory_file->proc_fops, sizeof(struct file_operations)); ++ memory_proc_file_ops.owner = THIS_MODULE; ++ memory_proc_file_ops.read = profile_memory_read; ++ memory_file->proc_fops = &memory_proc_file_ops; ++ } ++ ++ } ++ else ++ { ++ vfree( DbgPrintBuffer ); ++ DbgPrintBuffer = NULL; ++ } ++ } ++ return( retCode ); ++} ++ ++ ++void uninit_profile( void ) ++{ ++ if (dbg_file) DbgPrint("Calling remove_proc_entry(Debug, NULL)\n"), remove_proc_entry( "Debug", dbg_dir ); ++ if (inode_file) DbgPrint("Calling remove_proc_entry(inode, NULL)\n"), remove_proc_entry( "inode", dbg_dir ); ++ if (dentry_file) DbgPrint("Calling remove_proc_entry(dentry, NULL)\n"), remove_proc_entry( "dentry", dbg_dir ); ++ if (memory_file) DbgPrint("Calling remove_proc_entry(memory, NULL)\n"), remove_proc_entry( "memory", dbg_dir ); ++ ++ if (dbg_dir && (dbg_dir != Novfs_Procfs_dir)) ++ { ++ DbgPrint("Calling remove_proc_entry(%s, NULL)\n", MODULE_NAME); ++ remove_proc_entry( MODULE_NAME, NULL ); ++ } ++} ++ ++ ++static ++ssize_t ++User_proc_write_DbgBuffer(struct file * file, const char __user *buf, size_t nbytes, loff_t *ppos) ++{ ++ ssize_t retval=nbytes; ++ u_char *lbuf, *p; ++ int i; ++ u_long cpylen; ++ ++ ++ UNUSED_VARIABLE( *ppos ); ++ ++ lbuf = Novfs_Malloc(nbytes+1, GFP_KERNEL); ++ if (lbuf) ++ { ++ cpylen = copy_from_user(lbuf, buf, nbytes); ++ ++ lbuf[nbytes] = 0; ++ DbgPrint("User_proc_write_DbgBuffer: %s\n", lbuf); ++ ++ for (i=0; lbuf[i] && lbuf[i] != '\n'; i++) ; ++ ++ if ( '\n' == lbuf[i] ) ++ { ++ lbuf[i] = '\0'; ++ } ++ ++ if ( !strcmp("on", lbuf)) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ DbgPrintOn = 1; ++ } ++ else if ( !strcmp("off", lbuf)) ++ { ++ DbgPrintOn = 0; ++ } ++ else if ( !strcmp("reset", lbuf)) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ } ++ else if ( NULL != (p = strchr(lbuf, ' '))) ++ { ++ *p++ = '\0'; ++ if ( !strcmp("syslog", lbuf)) ++ { ++ ++ if (!strcmp("on", p)) ++ { ++ DbgSyslogOn = 1; ++ } ++ else if (!strcmp("off", p)) ++ { ++ DbgSyslogOn = 0; ++ } ++ } ++ else if ( !strcmp("novfsd", lbuf)) ++ { ++ Daemon_SendDebugCmd( p ); ++ } ++ else if ( !strcmp("file_update_timeout", lbuf)) ++ { ++ File_update_timeout = simple_strtoul(p, NULL, 0); ++ } ++ else if ( !strcmp("cache", lbuf)) ++ { ++ if (!strcmp("on", p)) ++ { ++ PageCache = 1; ++ } ++ else if (!strcmp("off", p)) ++ { ++ PageCache = 0; ++ } ++ } ++ } ++ Novfs_Free(lbuf); ++ } ++ ++ return (retval); ++} ++ ++static ++ssize_t ++User_proc_read_DbgBuffer(struct file * file, char * buf, size_t nbytes, loff_t *ppos) ++ ++{ ++ ssize_t retval=0; ++ size_t count; ++ ++ UNUSED_VARIABLE( *ppos ); ++ ++ if (0 != (count = DbgPrintBufferOffset - DbgPrintBufferReadOffset)) ++ { ++ ++ if (count > nbytes) ++ { ++ count = nbytes; ++ } ++ ++ count -= copy_to_user(buf, &DbgPrintBuffer[DbgPrintBufferReadOffset], count); ++ ++ if (count == 0) ++ { ++ if (retval == 0) ++ retval = -EFAULT; ++ } ++ else ++ { ++ DbgPrintBufferReadOffset += count; ++ if (DbgPrintBufferReadOffset >= DbgPrintBufferOffset) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ } ++ retval = count; ++ } ++ } ++ ++ return retval; ++} ++ ++static ++int ++proc_read_DbgBuffer(char *page, char **start, ++ off_t off, int count, ++ int *eof, void *data) ++{ ++ int len; ++ static char bufd[512]; ++ ++ UNUSED_VARIABLE(start); ++ UNUSED_VARIABLE(eof); ++ UNUSED_VARIABLE(data); ++ ++ sprintf(bufd, KERN_ALERT "proc_read_DbgBuffer: off=%ld count=%d DbgPrintBufferOffset=%lu DbgPrintBufferReadOffset=%lu\n", ++ off, count, DbgPrintBufferOffset, DbgPrintBufferReadOffset); ++ printk(bufd); ++ ++ len = DbgPrintBufferOffset - DbgPrintBufferReadOffset; ++ ++ if ((int)(DbgPrintBufferOffset-DbgPrintBufferReadOffset) > count) ++ { ++ len = count; ++ } ++ ++ if (len) ++ { ++ memcpy(page, &DbgPrintBuffer[DbgPrintBufferReadOffset], len); ++ DbgPrintBufferReadOffset += len; ++ } ++ ++ ++ if (DbgPrintBufferReadOffset >= DbgPrintBufferOffset) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ } ++ ++ sprintf(bufd, KERN_ALERT "proc_read_DbgBuffer: return %d\n", len); ++ printk(bufd); ++ ++ return len; ++} ++ ++#define DBG_BUFFER_SIZE (2*1024) ++ ++int ++LocalPrint( char *Fmt, ... ) ++{ ++ int len=0; ++ va_list args; ++ ++ if (DbgPrintBuffer) ++ { ++ va_start(args, Fmt); ++ len += vsnprintf(DbgPrintBuffer+DbgPrintBufferOffset, DbgPrintBufferSize-DbgPrintBufferOffset, Fmt, args); ++ DbgPrintBufferOffset += len; ++ } ++ ++ return(len); ++} ++ ++ ++int ++DbgPrint( char *Fmt, ... ) ++{ ++ char *buf; ++ int len=0; ++ unsigned long offset; ++ va_list args; ++ ++ if ( (DbgPrintBuffer && DbgPrintOn) || DbgSyslogOn ) ++ { ++ buf = kmalloc( DBG_BUFFER_SIZE, GFP_KERNEL ); ++ ++ if (buf) ++ { ++ va_start(args, Fmt); ++ len = sprintf(buf, "[%d] ", current->pid); ++ ++ len += vsnprintf(buf+len, DBG_BUFFER_SIZE-len, Fmt, args); ++ if ( -1 == len ) ++ { ++ len = DBG_BUFFER_SIZE-1; ++ buf[len] = '\0'; ++ } ++ /* ++ len = sprintf(&DbgPrintBuffer[offset], "[%llu] ", ts); ++ len += vsprintf(&DbgPrintBuffer[offset+len], Fmt, args); ++ */ ++ ++ if (len) ++ { ++ if (DbgSyslogOn) ++ { ++ printk("<6>%s", buf); ++ } ++ ++ if ( DbgPrintBuffer && DbgPrintOn ) ++ { ++ if ((DbgPrintBufferOffset+len) > DbgPrintBufferSize) ++ { ++ offset = DbgPrintBufferOffset; ++ DbgPrintBufferOffset = 0; ++ memset(&DbgPrintBuffer[offset], 0, DbgPrintBufferSize-offset); ++ } ++ ++ mb(); ++ ++ if ((DbgPrintBufferOffset+len) < DbgPrintBufferSize) ++ { ++ DbgPrintBufferOffset += len; ++ offset = DbgPrintBufferOffset-len; ++ memcpy(&DbgPrintBuffer[offset], buf, len+1); ++ } ++ } ++ } ++ kfree(buf); ++ } ++ } ++ ++ return(len); ++} ++ ++void ++__cyg_profile_func_enter (void *this_fn, void *call_site) ++{ ++ PSYMBOL_TABLE sym; ++ uint64_t t64; ++ ++ ++ if ((void *)init_novfs == this_fn) ++ { ++ DbgPrintBuffer = vmalloc(DBGBUFFERSIZE); ++ taskexit_nb.notifier_call = profile_task_exit_callback; ++ ++#ifdef CONFIG_KDB ++ kdb_register("novfs_tl", profile_dump_tasklist, "", "Dumps task list", 0); ++ kdb_register("novfs_st", profile_dump_scopetable, "", "Dumps the novfs scope table", 0); ++ kdb_register("novfs_dque", profile_dump_daemonque, "", "Dumps the novfs daemon que", 0); ++ kdb_register("novfs_db", profile_dump_DbgBuffer, "[-r] [-e size] [-i]", "Dumps the novfs DbgBuffer", 0); ++ kdb_register("novfs_den", profile_dump_DentryTree, "[dentry]", "Dumps a Dentry tree", 0); ++ kdb_register("novfs_ic", Novfs_dump_inode_cache, "[inode]", "Dumps a Inode Cache", 0); ++ kdb_register("novfs_inode", profile_dump_inode, "", "Dump allocated Inodes", 0); ++ kdb_register("novfs_mem", profile_dump_memorylist_dbg, "", "Dumps allocated memory", 0); ++#endif ++ } ++ else if (exit_novfs == this_fn) ++ { ++ /* ++ if (dbg_file) DbgPrint("Calling remove_proc_entry(Debug, NULL)\n"), remove_proc_entry( "Debug", dbg_dir ); ++ if (inode_file) DbgPrint("Calling remove_proc_entry(inode, NULL)\n"), remove_proc_entry( "inode", dbg_dir ); ++ if (dentry_file) DbgPrint("Calling remove_proc_entry(dentry, NULL)\n"), remove_proc_entry( "dentry", dbg_dir ); ++ if (memory_file) DbgPrint("Calling remove_proc_entry(memory, NULL)\n"), remove_proc_entry( "memory", dbg_dir ); ++ ++ if (dbg_dir && (dbg_dir != Novfs_Procfs_dir)) ++ { ++ printk( KERN_INFO "Calling remove_proc_entry(%s, NULL)\n", MODULE_NAME); ++ remove_proc_entry( MODULE_NAME, NULL ); ++ } ++ */ ++ } ++ ++ sym = SymbolTable; ++ while (sym->address) ++ { ++ if (this_fn == sym->address ) ++ { ++ t64 = get_nanosecond_time(); ++ DbgPrint("[%llu]%sS %s (0x%p 0x%p)\n", t64, &IndentString[sizeof(IndentString)-Indent-1], sym->name, this_fn, call_site); ++ ++ Indent++; ++ if (Indent > (int)(sizeof(IndentString)-1)) ++ Indent--; ++ ++ break; ++ } ++ sym++; ++ } ++} ++ ++void ++__cyg_profile_func_exit (void *this_fn, void *call_site) ++{ ++ PSYMBOL_TABLE sym; ++ uint64_t t64; ++ ++ if (exit_novfs == this_fn) ++ { ++ if (DbgPrintBuffer) vfree( DbgPrintBuffer ); ++ DbgPrintBuffer = NULL; ++ ++#ifdef CONFIG_KDB ++ kdb_unregister("novfs_tl"); ++ kdb_unregister("novfs_st"); ++ kdb_unregister("novfs_dque"); ++ kdb_unregister("novfs_db"); ++ kdb_unregister("novfs_den"); ++ kdb_unregister("novfs_ic"); ++ kdb_unregister("novfs_inode"); ++ kdb_unregister("novfs_mem"); ++#endif ++ return; ++ } ++ ++ sym = SymbolTable; ++ while (sym->address) ++ { ++ if (this_fn == sym->address ) ++ { ++ Indent--; ++ if (Indent < 0) ++ Indent = 0; ++ ++ t64 = get_nanosecond_time(); ++ DbgPrint("[%llu]%sR %s (0x%p)\n", t64, &IndentString[sizeof(IndentString)-Indent-1], sym->name, call_site); ++ break; ++ } ++ sym++; ++ } ++} ++ ++void ++doline(unsigned char *b, unsigned char *e, unsigned char *l) ++{ ++ *b++ = ' '; ++ while (l < e) { ++ if ((*l < ' ') || (*l > '~')) ++ { ++ *b++ = '.'; ++ *b = '\0'; ++ } ++ else ++ { ++ b += sprintf(b, "%c", *l); ++ } ++ l++; ++ } ++} ++ ++void ++mydump(int size, void *dumpptr) ++{ ++ unsigned char *ptr = (unsigned char *)dumpptr; ++ unsigned char *line=0, buf[80], *bptr=buf; ++ int i; ++ ++ if ( DbgPrintBuffer ) ++ { ++ if (size) ++ { ++ for (i=0; i < size; i++) ++ { ++ if (0 == (i % 16)) ++ { ++ if (line) ++ { ++ doline(bptr, ptr, line); ++ DbgPrint("%s\n", buf); ++ bptr = buf; ++ } ++ bptr += sprintf(bptr, "0x%p: ", ptr); ++ line = ptr; ++ } ++ bptr += sprintf(bptr, "%02x ", *ptr++); ++ } ++ doline(bptr, ptr, line); ++ DbgPrint("%s\n", buf); ++ } ++ } ++} ++ ++#define FEBRUARY 2 ++#define STARTOFTIME 1970 ++#define SECDAY 86400L ++#define SECYR (SECDAY * 365) ++#define leapyear(year) ((year) % 4 == 0) ++#define days_in_year(a) (leapyear(a) ? 366 : 365) ++#define days_in_month(a) (month_days[(a) - 1]) ++ ++static int month_days[12] = { ++ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ++}; ++ ++/* ++ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) ++ */ ++void ++GregorianDay(struct local_rtc_time * tm) ++{ ++ int leapsToDate; ++ int lastYear; ++ int day; ++ int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; ++ ++ lastYear=tm->tm_year-1; ++ ++ /* ++ * Number of leap corrections to apply up to end of last year ++ */ ++ leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; ++ ++ /* ++ * This year is a leap year if it is divisible by 4 except when it is ++ * divisible by 100 unless it is divisible by 400 ++ * ++ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be ++ */ ++ if((tm->tm_year%4==0) && ++ ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && ++ (tm->tm_mon>2)) ++ { ++ /* ++ * We are past Feb. 29 in a leap year ++ */ ++ day=1; ++ } ++ else ++ { ++ day=0; ++ } ++ ++ day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + ++ tm->tm_mday; ++ ++ tm->tm_wday=day%7; ++} ++ ++void ++to_tm(int tim, struct local_rtc_time * tm) ++{ ++ register int i; ++ register long hms, day; ++ ++ day = tim / SECDAY; ++ hms = tim % SECDAY; ++ ++ /* Hours, minutes, seconds are easy */ ++ tm->tm_hour = hms / 3600; ++ tm->tm_min = (hms % 3600) / 60; ++ tm->tm_sec = (hms % 3600) % 60; ++ ++ /* Number of years in days */ ++ for (i = STARTOFTIME; day >= days_in_year(i); i++) ++ day -= days_in_year(i); ++ tm->tm_year = i; ++ ++ /* Number of months in days left */ ++ if (leapyear(tm->tm_year)) ++ days_in_month(FEBRUARY) = 29; ++ for (i = 1; day >= days_in_month(i); i++) ++ day -= days_in_month(i); ++ days_in_month(FEBRUARY) = 28; ++ tm->tm_mon = i; ++ ++ /* Days are what is left over (+1) from all that. */ ++ tm->tm_mday = day + 1; ++ ++ /* ++ * Determine the day of week ++ */ ++ GregorianDay(tm); ++} ++ ++char * ++ctime_r(time_t *clock, char *buf) ++{ ++ struct local_rtc_time tm; ++ static char *DAYOFWEEK[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; ++ static char *MONTHOFYEAR[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; ++ ++ to_tm(*clock, &tm); ++ ++ sprintf(buf, "%s %s %d %d:%02d:%02d %d", DAYOFWEEK[tm.tm_wday], MONTHOFYEAR[tm.tm_mon-1], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year); ++ return(buf); ++} ++ ++ ++#ifdef CONFIG_KDB ++ ++int ++NO_TRACE ++profile_dump_tasklist(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++ Scope_Dump_Tasklist(); ++ return( 0 ); ++} ++ ++int ++NO_TRACE ++profile_dump_scopetable(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++ Scope_Dump_Scopetable(); ++ return( 0 ); ++} ++ ++int ++NO_TRACE ++profile_dump_daemonque(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++ Daemon_Dumpque(); ++ return( 0 ); ++} ++ ++int ++NO_TRACE ++profile_dump_DbgBuffer(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++ unsigned long offset = DbgPrintBufferReadOffset; ++ if (argc > 0) ++ { ++ if (!strcmp("-r", argv[1])) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ } ++ else if (!strcmp("-e", argv[1]) && (argc > 1)) ++ { ++ offset = simple_strtoul(argv[2], NULL, 0); ++ if (offset && offset < DbgPrintBufferOffset) ++ { ++ offset = DbgPrintBufferOffset - offset; ++ } ++ else ++ { ++ offset = DbgPrintBufferOffset; ++ } ++ } ++ else if (!strcmp("-i", argv[1])) ++ { ++ kdb_printf("DbgPrintBuffer =0x%p\n", DbgPrintBuffer); ++ kdb_printf("DbgPrintBufferOffset =0x%lx\n", DbgPrintBufferOffset); ++ kdb_printf("DbgPrintBufferSize =0x%lx\n", DbgPrintBufferSize); ++ offset = DbgPrintBufferOffset; ++ ++ } ++ } ++ while (DbgPrintBufferOffset > offset) ++ { ++ kdb_printf("%c", DbgPrintBuffer[offset++]); ++ } ++ return( 0 ); ++} ++ ++int ++NO_TRACE ++profile_dump_DentryTree(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++ struct dentry *parent=Novfs_root; ++ ++ if (argc > 0) ++ { ++ parent = (void *)simple_strtoul(argv[1], NULL, 0); ++ } ++ ++ if (parent) ++ { ++ profile_dump_dt(parent, kdb_printf ); ++ } ++ ++ return(0); ++} ++ ++ ++int ++NO_TRACE ++profile_dump_inode(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++ Novfs_dump_inode( kdb_printf ); ++ return( 0 ); ++} ++ ++#endif /* CONFIG_KDB */ ++ ++typedef struct memory_header ++{ ++ struct list_head list; ++ void *caller; ++ size_t size; ++} MEMORY_LIST, *PMEMORY_LIST; ++ ++spinlock_t Malloc_Lock = SPIN_LOCK_UNLOCKED; ++LIST_HEAD( Memory_List ); ++ ++void *Novfs_Malloc( size_t size, int flags ) ++{ ++ void *p=NULL; ++ PMEMORY_LIST mh; ++ ++ mh = kmalloc(size + sizeof(MEMORY_LIST), flags); ++ if (mh) ++ { ++ mh->caller = __builtin_return_address(0); ++ mh->size = size; ++ spin_lock(&Malloc_Lock); ++ list_add(&mh->list, &Memory_List); ++ spin_unlock(&Malloc_Lock); ++ p = (char *)mh+sizeof(MEMORY_LIST); ++ /*DbgPrint("Novfs_Malloc: 0x%p 0x%p %d\n", p, mh->caller, size); ++ */ ++ } ++ return(p); ++} ++ ++void Novfs_Free( const void *p ) ++{ ++ PMEMORY_LIST mh; ++ ++ if (p) ++ { ++ /*DbgPrint("Novfs_Free: 0x%p 0x%p\n", p, __builtin_return_address(0)); ++ */ ++ mh = (PMEMORY_LIST)((char *)p-sizeof(MEMORY_LIST)); ++ ++ spin_lock(&Malloc_Lock); ++ list_del(&mh->list); ++ spin_unlock(&Malloc_Lock); ++ kfree(mh); ++ } ++} ++ ++ ++int ++NO_TRACE ++profile_dump_memorylist_dbg(int argc, const char **argv, const char **envp, struct pt_regs *regs) ++{ ++#ifdef CONFIG_KDB ++ profile_dump_memorylist(kdb_printf); ++#endif /* CONFIG_KDB */ ++ ++ return( 0 ); ++} ++ ++void ++NO_TRACE ++profile_dump_memorylist( void *pf ) ++{ ++ void (*pfunc)(char *Fmt, ...) = pf; ++ ++ PMEMORY_LIST mh; ++ struct list_head *l; ++ ++ size_t total=0; ++ int count=0; ++ ++ spin_lock( &Malloc_Lock ); ++ ++ list_for_each( l, &Memory_List ) ++ { ++ mh = list_entry(l, MEMORY_LIST, list); ++ pfunc("0x%p 0x%p 0x%p %d\n", mh, (char *)mh+sizeof(MEMORY_LIST), mh->caller, mh->size); ++ count++; ++ total += mh->size; ++ } ++ spin_unlock( &Malloc_Lock ); ++ ++ pfunc("Blocks=%d Total=%d\n", count, total); ++} ++ ++void ++NO_TRACE ++profile_dump_dt(struct dentry *parent, void *pf ) ++{ ++ void (*pfunc)(char *Fmt, ...) = pf; ++ struct l { ++ struct l *next; ++ struct dentry *dentry; ++ } *l, *n, *start; ++ struct list_head *p; ++ struct dentry *d; ++ char *buf, *path, *sd; ++ char inode_number[16]; ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ ++ if( NULL == buf ) ++ { ++ return; ++ } ++ ++ if (parent) ++ { ++ pfunc("starting 0x%p %.*s\n", parent, parent->d_name.len, parent->d_name.name); ++ if (parent->d_subdirs.next == &parent->d_subdirs) ++ { ++ pfunc("No children...\n"); ++ } ++ else ++ { ++ start = Novfs_Malloc(sizeof(*start), GFP_KERNEL); ++ if (start) ++ { ++ start->next = NULL; ++ start->dentry = parent; ++ l = start; ++ while(l) ++ { ++ p = l->dentry->d_subdirs.next; ++ while(p != &l->dentry->d_subdirs) ++ { ++ d = list_entry(p, struct dentry, D_CHILD); ++ p = p->next; ++ ++ if (d->d_subdirs.next != &d->d_subdirs) ++ { ++ n = Novfs_Malloc(sizeof(*n), GFP_KERNEL); ++ if (n) ++ { ++ n->next = l->next; ++ l->next = n; ++ n->dentry = d; ++ } ++ } ++ else ++ { ++ path = Scope_dget_path(d, buf, PATH_LENGTH_BUFFER, 1); ++ if (path) ++ { ++ pfunc("1-0x%p %s\n" \ ++ " d_name: %.*s\n" \ ++ " d_parent: 0x%p\n" \ ++ " d_count: %d\n" \ ++ " d_flags: 0x%x\n" \ ++ " d_subdirs: 0x%p\n" \ ++ " d_inode: 0x%p\n", ++ d, path, d->d_name.len, d->d_name.name, d->d_parent, ++ atomic_read(&d->d_count), d->d_flags, d->d_subdirs.next, d->d_inode); ++ } ++ } ++ } ++ l = l->next; ++ } ++ l = start; ++ while(l) ++ { ++ d=l->dentry; ++ path = Scope_dget_path(d, buf, PATH_LENGTH_BUFFER, 1); ++ if (path) ++ { ++ sd = " (None)"; ++ if (&d->d_subdirs != d->d_subdirs.next) ++ { ++ sd = ""; ++ } ++ inode_number[0] = '\0'; ++ if (d->d_inode) ++ { ++ sprintf(inode_number, " (%lu)", d->d_inode->i_ino); ++ } ++ pfunc("0x%p %s\n" \ ++ " d_parent: 0x%p\n" \ ++ " d_count: %d\n" \ ++ " d_flags: 0x%x\n" \ ++ " d_subdirs: 0x%p%s\n" \ ++ " d_inode: 0x%p%s\n", ++ d, path, d->d_parent, ++ atomic_read(&d->d_count), d->d_flags, d->d_subdirs.next, sd, d->d_inode, inode_number); ++ } ++ ++ n = l; ++ l = l->next; ++ Novfs_Free(n); ++ } ++ } ++ } ++ } ++ ++ Novfs_Free(buf); ++ ++} ++ ++/*int profile_inode_open(struct inode *inode, struct file *file) ++{ ++ ++} ++ ++int profile_inode_close(struct inode *inode, struct file *file) ++{ ++} ++*/ ++ssize_t profile_common_read( char *buf, size_t len, loff_t *off ) ++{ ++ ssize_t retval=0; ++ size_t count; ++ unsigned long offset = *off; ++ ++ if (0 != (count = DbgPrintBufferOffset - offset)) ++ { ++ if (count > len) ++ { ++ count = len; ++ } ++ ++ count -= copy_to_user(buf, &DbgPrintBuffer[offset], count); ++ ++ if (count == 0) ++ { ++ retval = -EFAULT; ++ } ++ else ++ { ++ *off += (loff_t)count; ++ retval = count; ++ } ++ } ++ return retval; ++ ++} ++ ++//ssize_t NO_TRACE profile_inode_read(struct file *file, char *buf, size_t len, loff_t *off) ++ssize_t profile_inode_read(struct file *file, char *buf, size_t len, loff_t *off) ++{ ++ ssize_t retval=0; ++ unsigned long offset = *off; ++ static char save_DbgPrintOn; ++ ++ if (offset == 0) ++ { ++ down(&LocalPrint_lock); ++ save_DbgPrintOn = DbgPrintOn; ++ DbgPrintOn = 0; ++ ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ Novfs_dump_inode( LocalPrint ); ++ } ++ ++ retval = profile_common_read(buf, len, off); ++ ++ if ( 0 == retval) ++ { ++ DbgPrintOn = save_DbgPrintOn; ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ ++ up(&LocalPrint_lock); ++ } ++ ++ return retval; ++ ++} ++ ++ssize_t NO_TRACE profile_dentry_read(struct file *file, char *buf, size_t len, loff_t *off) ++{ ++ ssize_t retval=0; ++ unsigned long offset = *off; ++ static char save_DbgPrintOn; ++ ++ if (offset == 0) ++ { ++ down(&LocalPrint_lock); ++ save_DbgPrintOn = DbgPrintOn; ++ DbgPrintOn = 0; ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ profile_dump_dt(Novfs_root, LocalPrint); ++ } ++ ++ retval = profile_common_read(buf, len, off); ++ ++ if ( 0 == retval) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ DbgPrintOn = save_DbgPrintOn; ++ ++ up(&LocalPrint_lock); ++ } ++ ++ return retval; ++ ++} ++ ++ssize_t NO_TRACE profile_memory_read(struct file *file, char *buf, size_t len, loff_t *off) ++{ ++ ssize_t retval=0; ++ unsigned long offset = *off; ++ static char save_DbgPrintOn; ++ ++ if (offset == 0) ++ { ++ down(&LocalPrint_lock); ++ save_DbgPrintOn = DbgPrintOn; ++ DbgPrintOn = 0; ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ profile_dump_memorylist( LocalPrint ); ++ } ++ ++ retval = profile_common_read(buf, len, off); ++ ++ if ( 0 == retval) ++ { ++ DbgPrintBufferOffset = DbgPrintBufferReadOffset = 0; ++ DbgPrintOn = save_DbgPrintOn; ++ ++ up(&LocalPrint_lock); ++ } ++ ++ return retval; ++ ++} ++ ++uint64_t get_nanosecond_time() ++{ ++ struct timespec ts; ++ uint64_t retVal; ++ ++ ts = current_kernel_time(); ++ ++ retVal = (uint64_t)NSEC_PER_SEC; ++ retVal *= (uint64_t)ts.tv_sec; ++ retVal += (uint64_t)ts.tv_nsec; ++ ++ return( retVal ); ++} +diff -uNr src.old/src/profile_funcs.h src/src/profile_funcs.h +--- src.old/src/profile_funcs.h 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/profile_funcs.h 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,415 @@ ++extern void Daemon_Added_Resource( void ); ++extern void Daemon_Close_Control( void ); ++extern void Daemon_CreateSessionId( void ); ++extern void Daemon_DestroySessionId( void ); ++extern void Daemon_Dumpque( void ); ++extern void Daemon_Get_UserSpace( void ); ++extern void Daemon_Library_close( void ); ++extern void Daemon_Library_ioctl( void ); ++extern void Daemon_Library_open( void ); ++extern void Daemon_Library_read( void ); ++extern void Daemon_Library_write( void ); ++extern void Daemon_Login( void ); ++extern void Daemon_Logout( void ); ++extern void Daemon_Open_Control( void ); ++extern void Daemon_Poll( void ); ++extern void Daemon_Receive_Reply( void ); ++extern void Daemon_Remove_Resource( void ); ++extern void Daemon_Send_Command( void ); ++extern void Daemon_SetMountPoint( void ); ++extern void Daemon_getpwuid( void ); ++extern void Daemon_getversion( void ); ++extern void Daemon_ioctl( void ); ++extern void GetConnData( void ); ++extern void GetUserData( void ); ++extern void Init_Daemon_Queue( void ); ++extern void Init_Procfs_Interface( void ); ++extern void Novfs_Add_to_Root( void ); ++extern void Novfs_Add_to_Root2( void ); ++extern void Novfs_Close_File( void ); ++extern void Novfs_Close_Stream( void ); ++extern void Novfs_Control_ioctl( void ); ++extern void Novfs_Control_read( void ); ++extern void Novfs_Control_write( void ); ++extern void Novfs_Create( void ); ++extern void Novfs_Delete( void ); ++extern void Novfs_Find_Name_In_List( void ); ++extern void Novfs_Get_Connected_Server_List( void ); ++extern void Novfs_Get_Directory_List( void ); ++extern void Novfs_Get_Directory_ListEx( void ); ++extern void Novfs_Get_File_Info( void ); ++extern void Novfs_Get_File_Info2( void ); ++extern void Novfs_Get_Server_Volume_List( void ); ++extern void Novfs_Get_Version( void ); ++extern void Novfs_Open_File( void ); ++extern void Novfs_Read_File( void ); ++extern void Novfs_Read_Stream( void ); ++extern void Novfs_Remove_from_Root( void ); ++extern void Novfs_Rename_File( void ); ++extern void Novfs_Set_Attr( void ); ++extern void Novfs_Truncate_File( void ); ++extern void Novfs_User_proc_ioctl( void ); ++extern void Novfs_User_proc_read( void ); ++extern void Novfs_User_proc_write( void ); ++extern void Novfs_Verify_Server_Name( void ); ++extern void Novfs_Verify_Volume_Name( void ); ++extern void Novfs_Write_File( void ); ++extern void Novfs_Write_Stream( void ); ++extern void Novfs_a_readpage( void ); ++extern void Novfs_add_inode_entry( void ); ++extern void Novfs_clear_inode( void ); ++extern void Novfs_d_add( void ); ++extern void Novfs_d_compare( void ); ++extern void Novfs_d_delete( void ); ++extern void Novfs_d_hash( void ); ++extern void Novfs_d_iput( void ); ++extern void Novfs_d_lookup( void ); ++extern void Novfs_d_release( void ); ++extern void Novfs_d_revalidate( void ); ++extern void Novfs_d_strcmp( void ); ++extern void Novfs_dget_path( void ); ++extern void Novfs_dir_fsync( void ); ++extern void Novfs_dir_lseek( void ); ++extern void Novfs_dir_open( void ); ++extern void Novfs_dir_read( void ); ++extern void Novfs_dir_readdir( void ); ++extern void Novfs_dir_release( void ); ++extern void Novfs_enumerate_inode_cache( void ); ++extern void Novfs_f_flush( void ); ++extern void Novfs_f_fsync( void ); ++extern void Novfs_f_ioctl( void ); ++extern void Novfs_f_llseek( void ); ++extern void Novfs_f_lock( void ); ++extern void Novfs_f_mmap( void ); ++extern void Novfs_f_open( void ); ++extern void Novfs_f_read( void ); ++extern void Novfs_f_readdir( void ); ++extern void Novfs_f_release( void ); ++extern void Novfs_f_write( void ); ++extern void Novfs_fill_super( void ); ++extern void Novfs_free_inode_cache( void ); ++extern void Novfs_free_invalid_entries( void ); ++extern void Novfs_get_alltrees( void ); ++extern void Novfs_get_entry( void ); ++extern void Novfs_get_entry_time( void ); ++extern void Novfs_get_inode( void ); ++extern void Novfs_get_remove_entry( void ); ++extern void Novfs_get_sb( void ); ++extern void Novfs_i_create( void ); ++extern void Novfs_i_getattr( void ); ++extern void Novfs_i_lookup( void ); ++extern void Novfs_i_mkdir( void ); ++extern void Novfs_i_mknod( void ); ++extern void Novfs_i_permission( void ); ++extern void Novfs_i_rename( void ); ++extern void Novfs_i_revalidate( void ); ++extern void Novfs_i_rmdir( void ); ++extern void Novfs_i_setattr( void ); ++extern void Novfs_i_unlink( void ); ++extern void Novfs_internal_hash( void ); ++extern void Novfs_invalidate_inode_cache( void ); ++extern void Novfs_kill_sb( void ); ++extern void Novfs_lock_inode_cache( void ); ++extern void Novfs_lookup_inode_cache( void ); ++extern void Novfs_lookup_validate( void ); ++extern void Novfs_notify_change( void ); ++extern void Novfs_read_inode( void ); ++extern void Novfs_remove_inode_entry( void ); ++extern void Novfs_show_options( void ); ++extern void Novfs_statfs( void ); ++extern void Novfs_tree_read( void ); ++extern void Novfs_unlock_inode_cache( void ); ++extern void Novfs_update_entry( void ); ++extern void Novfs_verify_file( void ); ++extern void Novfs_write_inode( void ); ++extern void NwAuthConnWithId( void ); ++extern void NwConnClose( void ); ++extern void NwGetConnInfo( void ); ++extern void NwGetDaemonVersion( void ); ++extern void NwGetIdentityInfo( void ); ++extern void NwLicenseConn( void ); ++extern void NwLoginIdentity( void ); ++extern void NwLogoutIdentity( void ); ++extern void NwOpenConnByAddr( void ); ++extern void NwOpenConnByName( void ); ++extern void NwOpenConnByRef( void ); ++extern void NwQueryFeature( void ); ++extern void NwRawSend( void ); ++extern void NwScanConnInfo( void ); ++extern void NwSetConnInfo( void ); ++extern void NwSysConnClose( void ); ++extern void NwUnAuthenticate( void ); ++extern void NwUnlicenseConn( void ); ++extern void NwcChangeAuthKey( void ); ++extern void NwcEnumIdentities( void ); ++extern void NwcEnumerateDrives( void ); ++extern void NwcGetBroadcastMessage( void ); ++extern void NwcGetDefaultNameCtx( void ); ++extern void NwcGetPreferredDSTree( void ); ++extern void NwcGetPrimaryConn( void ); ++extern void NwcGetTreeMonitoredConn( void ); ++extern void NwcSetDefaultNameCtx( void ); ++extern void NwcSetMapDrive( void ); ++extern void NwcSetPreferredDSTree( void ); ++extern void NwcSetPrimaryConn( void ); ++extern void NwcUnMapDrive( void ); ++extern void NwdConvertLocalHandle( void ); ++extern void NwdConvertNetwareHandle( void ); ++extern void NwdGetMountPath( void ); ++extern void NwdSetKeyValue( void ); ++extern void NwdSetMapDrive( void ); ++extern void NwdUnMapDrive( void ); ++extern void NwdVerifyKeyValue( void ); ++extern void Queue_Daemon_Command( void ); ++extern void Queue_get( void ); ++extern void Queue_put( void ); ++extern void RemoveDriveMaps( void ); ++extern void Scope_Cleanup( void ); ++extern void Scope_Cleanup_Thread( void ); ++extern void Scope_Dump_Scopetable( void ); ++extern void Scope_Dump_Tasklist( void ); ++extern void Scope_Find_Scope( void ); ++extern void Scope_Get_Hash( void ); ++extern void Scope_Get_ScopeUsers( void ); ++extern void Scope_Get_ScopefromName( void ); ++extern void Scope_Get_ScopefromPath( void ); ++extern void Scope_Get_SessionId( void ); ++extern void Scope_Get_Uid( void ); ++extern void Scope_Get_UserName( void ); ++extern void Scope_Get_UserSpace( void ); ++extern void Scope_Init( void ); ++extern void Scope_Lookup( void ); ++extern void Scope_Search4Scope( void ); ++extern void Scope_Set_UserSpace( void ); ++extern void Scope_Timer_Function( void ); ++extern void Scope_Uninit( void ); ++extern void Scope_Validate_Scope( void ); ++extern void Uninit_Daemon_Queue( void ); ++extern void Uninit_Procfs_Interface( void ); ++extern void add_to_list( void ); ++extern void begin_directory_enumerate( void ); ++extern void directory_enumerate( void ); ++extern void directory_enumerate_ex( void ); ++extern void do_login( void ); ++extern void do_logout( void ); ++extern void end_directory_enumerate( void ); ++extern void exit_novfs( void ); ++extern void find_queue( void ); ++extern void get_next_queue( void ); ++extern void init_novfs( void ); ++extern void local_unlink( void ); ++extern void process_list( void ); ++extern void update_inode( void ); ++extern void verify_dentry( void ); ++ ++SYMBOL_TABLE SymbolTable[] = { ++ {Scope_Get_UserSpace, "Scope_Get_UserSpace"}, ++ {NwLoginIdentity, "NwLoginIdentity"}, ++ {Novfs_d_revalidate, "Novfs_d_revalidate"}, ++ {Daemon_SetMountPoint, "Daemon_SetMountPoint"}, ++ {Scope_Get_Hash, "Scope_Get_Hash"}, ++ {Queue_get, "Queue_get"}, ++ {Queue_Daemon_Command, "Queue_Daemon_Command"}, ++ {Novfs_dir_fsync, "Novfs_dir_fsync"}, ++ {Novfs_Read_File, "Novfs_Read_File"}, ++ {Daemon_Library_close, "Daemon_Library_close"}, ++ {NwRawSend, "NwRawSend"}, ++ {Novfs_get_inode, "Novfs_get_inode"}, ++ {Novfs_Remove_from_Root, "Novfs_Remove_from_Root"}, ++ {Novfs_Find_Name_In_List, "Novfs_Find_Name_In_List"}, ++ {Scope_Get_SessionId, "Scope_Get_SessionId"}, ++ {NwOpenConnByAddr, "NwOpenConnByAddr"}, ++ {Novfs_read_inode, "Novfs_read_inode"}, ++ {Novfs_Truncate_File, "Novfs_Truncate_File"}, ++ {Daemon_Login, "Daemon_Login"}, ++ {Scope_Get_ScopefromPath, "Scope_Get_ScopefromPath"}, ++ {NwcGetTreeMonitoredConn, "NwcGetTreeMonitoredConn"}, ++ {Novfs_write_inode, "Novfs_write_inode"}, ++ {Scope_Lookup, "Scope_Lookup"}, ++ {NwQueryFeature, "NwQueryFeature"}, ++ {Novfs_get_entry_time, "Novfs_get_entry_time"}, ++ {Novfs_Control_write, "Novfs_Control_write"}, ++ {Scope_Get_Uid, "Scope_Get_Uid"}, ++ {NwSysConnClose, "NwSysConnClose"}, ++ {NwConnClose, "NwConnClose"}, ++ {Novfs_get_entry, "Novfs_get_entry"}, ++ {Novfs_Rename_File, "Novfs_Rename_File"}, ++ {NwdConvertLocalHandle, "NwdConvertLocalHandle"}, ++ {Novfs_dir_lseek, "Novfs_dir_lseek"}, ++ {Scope_Get_ScopefromName, "Scope_Get_ScopefromName"}, ++ {NwcGetPrimaryConn, "NwcGetPrimaryConn"}, ++ {Novfs_d_strcmp, "Novfs_d_strcmp"}, ++ {Daemon_Library_ioctl, "Daemon_Library_ioctl"}, ++ {end_directory_enumerate, "end_directory_enumerate"}, ++ {directory_enumerate, "directory_enumerate"}, ++ {begin_directory_enumerate, "begin_directory_enumerate"}, ++ {NwdGetMountPath, "NwdGetMountPath"}, ++ {NwAuthConnWithId, "NwAuthConnWithId"}, ++ {Novfs_Set_Attr, "Novfs_Set_Attr"}, ++ {Daemon_getversion, "Daemon_getversion"}, ++ {Scope_Dump_Scopetable, "Scope_Dump_Scopetable"}, ++ {NwcSetMapDrive, "NwcSetMapDrive"}, ++ {Novfs_lookup_inode_cache, "Novfs_lookup_inode_cache"}, ++ {Novfs_i_mkdir, "Novfs_i_mkdir"}, ++ {Novfs_free_invalid_entries, "Novfs_free_invalid_entries"}, ++ {Novfs_dump_inode_cache, "Novfs_dump_inode_cache"}, ++ {Novfs_Write_Stream, "Novfs_Write_Stream"}, ++ {Novfs_Verify_Server_Name, "Novfs_Verify_Server_Name"}, ++ {GetConnData, "GetConnData"}, ++ {Uninit_Procfs_Interface, "Uninit_Procfs_Interface"}, ++ {Scope_Validate_Scope, "Scope_Validate_Scope"}, ++ {Scope_Timer_Function, "Scope_Timer_Function"}, ++ {Novfs_i_setattr, "Novfs_i_setattr"}, ++ {Novfs_i_mknod, "Novfs_i_mknod"}, ++ {Novfs_Verify_Volume_Name, "Novfs_Verify_Volume_Name"}, ++ {Novfs_Close_Stream, "Novfs_Close_Stream"}, ++ {Novfs_Add_to_Root, "Novfs_Add_to_Root"}, ++ {Init_Procfs_Interface, "Init_Procfs_Interface"}, ++ {Novfs_dump_inode, "Novfs_dump_inode"}, ++ {Novfs_Get_Directory_List, "Novfs_Get_Directory_List"}, ++ {Novfs_Get_Connected_Server_List, "Novfs_Get_Connected_Server_List"}, ++ {Daemon_Logout, "Daemon_Logout"}, ++ {do_logout, "do_logout"}, ++ {Scope_Search4Scope, "Scope_Search4Scope"}, ++ {NwdUnMapDrive, "NwdUnMapDrive"}, ++ {Novfs_Control_read, "Novfs_Control_read"}, ++ {Scope_Cleanup_Thread, "Scope_Cleanup_Thread"}, ++ {Novfs_invalidate_inode_cache, "Novfs_invalidate_inode_cache"}, ++ {Novfs_f_flush, "Novfs_f_flush"}, ++ {Novfs_enumerate_inode_cache, "Novfs_enumerate_inode_cache"}, ++ {Novfs_d_compare, "Novfs_d_compare"}, ++ {Daemon_Library_write, "Daemon_Library_write"}, ++ {GetUserData, "GetUserData"}, ++ {Daemon_Remove_Resource, "Daemon_Remove_Resource"}, ++ {Scope_Set_UserSpace, "Scope_Set_UserSpace"}, ++ {Novfs_get_alltrees, "Novfs_get_alltrees"}, ++ {Daemon_Get_UserSpace, "Daemon_Get_UserSpace"}, ++ {Uninit_Daemon_Queue, "Uninit_Daemon_Queue"}, ++ {NwcChangeAuthKey, "NwcChangeAuthKey"}, ++ {NwLicenseConn, "NwLicenseConn"}, ++ {Init_Daemon_Queue, "Init_Daemon_Queue"}, ++ {Novfs_tree_read, "Novfs_tree_read"}, ++ {Novfs_f_llseek, "Novfs_f_llseek"}, ++ {find_queue, "find_queue"}, ++ {Scope_Find_Scope, "Scope_Find_Scope"}, ++ {Novfs_lookup_validate, "Novfs_lookup_validate"}, ++ {Novfs_d_hash, "Novfs_d_hash"}, ++ {Novfs_a_readpage, "Novfs_a_readpage"}, ++ {Novfs_Create, "Novfs_Create"}, ++ {Novfs_Close_File, "Novfs_Close_File"}, ++ {Daemon_getpwuid, "Daemon_getpwuid"}, ++ {Daemon_CreateSessionId, "Daemon_CreateSessionId"}, ++ {Scope_dget_path, "Scope_dget_path"}, ++ {NwcSetDefaultNameCtx, "NwcSetDefaultNameCtx"}, ++ {NwcGetDefaultNameCtx, "NwcGetDefaultNameCtx"}, ++ {NwUnAuthenticate, "NwUnAuthenticate"}, ++ {Novfs_i_getattr, "Novfs_i_getattr"}, ++ {Novfs_get_remove_entry, "Novfs_get_remove_entry"}, ++ {Novfs_f_ioctl, "Novfs_f_ioctl"}, ++ {Scope_Get_ScopeUsers, "Scope_Get_ScopeUsers"}, ++ {Scope_Dump_Tasklist, "Scope_Dump_Tasklist"}, ++ {NwOpenConnByRef, "NwOpenConnByRef"}, ++ {Novfs_unlock_inode_cache, "Novfs_unlock_inode_cache"}, ++ {Novfs_lock_inode_cache, "Novfs_lock_inode_cache"}, ++ {Daemon_DestroySessionId, "Daemon_DestroySessionId"}, ++ {do_login, "do_login"}, ++ {Novfs_free_inode_cache, "Novfs_free_inode_cache"}, ++ {Novfs_Read_Stream, "Novfs_Read_Stream"}, ++ {Daemon_Library_read, "Daemon_Library_read"}, ++ {NwdSetMapDrive, "NwdSetMapDrive"}, ++ {Novfs_internal_hash, "Novfs_internal_hash"}, ++ {Daemon_Receive_Reply, "Daemon_Receive_Reply"}, ++ {Daemon_Library_open, "Daemon_Library_open"}, ++ {get_next_queue, "get_next_queue"}, ++ {exit_novfs, "exit_novfs"}, ++ {NwcGetBroadcastMessage, "NwcGetBroadcastMessage"}, ++ {Novfs_d_lookup, "Novfs_d_lookup"}, ++ {Novfs_clear_inode, "Novfs_clear_inode"}, ++ {Daemon_Open_Control, "Daemon_Open_Control"}, ++ {NwdConvertNetwareHandle, "NwdConvertNetwareHandle"}, ++ {NwcUnMapDrive, "NwcUnMapDrive"}, ++ {Novfs_notify_change, "Novfs_notify_change"}, ++ {Novfs_dir_release, "Novfs_dir_release"}, ++ {directory_enumerate_ex, "directory_enumerate_ex"}, ++ {RemoveDriveMaps, "RemoveDriveMaps"}, ++ {NwOpenConnByName, "NwOpenConnByName"}, ++ {Novfs_verify_file, "Novfs_verify_file"}, ++ {Novfs_statfs, "Novfs_statfs"}, ++ {Novfs_f_write, "Novfs_f_write"}, ++ {Novfs_Get_File_Info, "Novfs_Get_File_Info"}, ++ {Novfs_Delete, "Novfs_Delete"}, ++ {update_inode, "update_inode"}, ++ {NwcSetPreferredDSTree, "NwcSetPreferredDSTree"}, ++ {NwcGetPreferredDSTree, "NwcGetPreferredDSTree"}, ++ {Novfs_update_entry, "Novfs_update_entry"}, ++ {Novfs_kill_sb, "Novfs_kill_sb"}, ++ {Daemon_ioctl, "Daemon_ioctl"}, ++ {Scope_Get_UserName, "Scope_Get_UserName"}, ++ {NwcEnumerateDrives, "NwcEnumerateDrives"}, ++ {Novfs_i_revalidate, "Novfs_i_revalidate"}, ++ {Novfs_f_release, "Novfs_f_release"}, ++ {Novfs_f_read, "Novfs_f_read"}, ++ {Novfs_d_delete, "Novfs_d_delete"}, ++ {Novfs_Write_File, "Novfs_Write_File"}, ++ {Novfs_User_proc_ioctl, "Novfs_User_proc_ioctl"}, ++ {Novfs_Get_File_Info2, "Novfs_Get_File_Info2"}, ++ {NwdSetKeyValue, "NwdSetKeyValue"}, ++ {Novfs_remove_inode_entry, "Novfs_remove_inode_entry"}, ++ {Novfs_i_rename, "Novfs_i_rename"}, ++ {Novfs_f_open, "Novfs_f_open"}, ++ {Novfs_d_iput, "Novfs_d_iput"}, ++ {Novfs_Get_Directory_ListEx, "Novfs_Get_Directory_ListEx"}, ++ {Daemon_Close_Control, "Daemon_Close_Control"}, ++ {verify_dentry, "verify_dentry"}, ++ {process_list, "process_list"}, ++ {local_unlink, "local_unlink"}, ++ {init_novfs, "init_novfs"}, ++ {NwUnlicenseConn, "NwUnlicenseConn"}, ++ {NwGetConnInfo, "NwGetConnInfo"}, ++ {Novfs_i_permission, "Novfs_i_permission"}, ++ {Novfs_dir_read, "Novfs_dir_read"}, ++ {NwcSetPrimaryConn, "NwcSetPrimaryConn"}, ++ {Novfs_f_lock, "Novfs_f_lock"}, ++ {Novfs_dir_readdir, "Novfs_dir_readdir"}, ++ {Novfs_dir_open, "Novfs_dir_open"}, ++ {Queue_put, "Queue_put"}, ++ {NwLogoutIdentity, "NwLogoutIdentity"}, ++ {NwGetIdentityInfo, "NwGetIdentityInfo"}, ++ {Novfs_i_rmdir, "Novfs_i_rmdir"}, ++ {Novfs_i_create, "Novfs_i_create"}, ++ {Novfs_f_mmap, "Novfs_f_mmap"}, ++ {Novfs_User_proc_read, "Novfs_User_proc_read"}, ++ {Novfs_show_options, "Novfs_show_options"}, ++ {Novfs_add_inode_entry, "Novfs_add_inode_entry"}, ++ {Novfs_Open_File, "Novfs_Open_File"}, ++ {Novfs_Get_Version, "Novfs_Get_Version"}, ++ {Daemon_Poll, "Daemon_Poll"}, ++ {add_to_list, "add_to_list"}, ++ {Scope_Init, "Scope_Init"}, ++ {Scope_Cleanup, "Scope_Cleanup"}, ++ {NwSetConnInfo, "NwSetConnInfo"}, ++ {Novfs_i_unlink, "Novfs_i_unlink"}, ++ {Novfs_get_sb, "Novfs_get_sb"}, ++ {Novfs_f_readdir, "Novfs_f_readdir"}, ++ {Novfs_f_fsync, "Novfs_f_fsync"}, ++ {Novfs_d_release, "Novfs_d_release"}, ++ {Novfs_User_proc_write, "Novfs_User_proc_write"}, ++ {Daemon_Send_Command, "Daemon_Send_Command"}, ++ {Daemon_Dumpque, "Daemon_Dumpque"}, ++ {NwcEnumIdentities, "NwcEnumIdentities"}, ++ {NwGetDaemonVersion, "NwGetDaemonVersion"}, ++ {Novfs_i_lookup, "Novfs_i_lookup"}, ++ {Novfs_fill_super, "Novfs_fill_super"}, ++ {Novfs_Get_Server_Volume_List, "Novfs_Get_Server_Volume_List"}, ++ {Novfs_Add_to_Root2, "Novfs_Add_to_Root2"}, ++ {Daemon_SendDebugCmd, "Daemon_SendDebugCmd"}, ++ {Daemon_Added_Resource, "Daemon_Added_Resource"}, ++ {Scope_Uninit, "Scope_Uninit"}, ++ {NwdVerifyKeyValue, "NwdVerifyKeyValue"}, ++ {NwScanConnInfo, "NwScanConnInfo"}, ++ {Novfs_dget_path, "Novfs_dget_path"}, ++ {Novfs_d_add, "Novfs_d_add"}, ++ {Novfs_Control_ioctl, "Novfs_Control_ioctl"}, ++ // Terminate the table ++ {NULL, NULL} ++}; +diff -uNr src.old/src/scope.c src/src/scope.c +--- src.old/src/scope.c 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/scope.c 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,1214 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: scope.c ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: This module contains functions used to scope ++ * users. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*===[ Include files specific to this module ]============================*/ ++#include "vfs.h" ++#define LEADER signal->leader ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) ++ typedef struct task_struct task_t; ++#endif ++ ++/*===[ External data ]====================================================*/ ++ ++/*===[ External prototypes ]==============================================*/ ++extern int DbgPrint( char *Fmt, ... ); ++extern int Daemon_CreateSessionId( uint64_t *SessionId ); ++extern int Daemon_DestroySessionId( uint64_t SessionId ); ++extern int Daemon_getpwuid( uid_t uid, int unamelen, char *uname ); ++extern int Daemon_Get_UserSpace( uint64_t SessionId, uint64_t *TotalSize, uint64_t *TotalFree, uint64_t *TotalDirectoryEnties, uint64_t *FreeDirectoryEnties); ++ ++extern int Novfs_Remove_from_Root(char *); ++extern int Novfs_Add_to_Root(char *); ++ ++/*===[ Manifest constants ]===============================================*/ ++#define CLEANUP_INTERVAL 10 ++#define MAX_USERNAME_LENGTH 32 ++ ++/*===[ Type definitions ]=================================================*/ ++typedef struct _SCOPE_LIST_ ++{ ++ struct list_head ScopeList; ++ scope_t ScopeId; ++ session_t SessionId; ++ pid_t ScopePid; ++ task_t *ScopeTask; ++ unsigned long ScopeHash; ++ uid_t ScopeUid; ++ uint64_t ScopeUSize; ++ uint64_t ScopeUFree; ++ uint64_t ScopeUTEnties; ++ uint64_t ScopeUAEnties; ++ int ScopeUserNameLength; ++ unsigned char ScopeUserName[MAX_USERNAME_LENGTH]; ++} SCOPE_LIST, *PSCOPE_LIST; ++ ++/*===[ Function prototypes ]==============================================*/ ++void Scope_Init( void ); ++void Scope_Uninit( void ); ++ ++PSCOPE_LIST Scope_Search4Scope( session_t Id, BOOLEAN Session, BOOLEAN Locked ); ++PSCOPE_LIST Scope_Find_Scope( BOOLEAN Create ); ++unsigned long Scope_Get_Hash( PSCOPE_LIST Scope ); ++uid_t Scope_Get_Uid( PSCOPE_LIST Scope ); ++int Scope_Validate_Scope( PSCOPE_LIST Scope ); ++char *Scope_Get_UserName( PSCOPE_LIST Scope ); ++session_t Scope_Get_SessionId( PSCOPE_LIST Scope ); ++PSCOPE_LIST Scope_Get_ScopefromName( struct qstr *Name ); ++int Scope_Set_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); ++int Scope_Get_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ); ++ ++char *Scope_Get_ScopeUsers( void ); ++void *Scope_Lookup( void ); ++ ++void Scope_Timer_Function(unsigned long Context); ++int Scope_Cleanup_Thread(void *Args); ++void Scope_Cleanup( void ); ++char *Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags); ++void Scope_Dump_Tasklist( void ); ++void Scope_Dump_Scopetable( void ); ++ ++/*===[ Global variables ]=================================================*/ ++struct list_head Scope_List; ++struct semaphore Scope_Lock; ++struct semaphore Scope_Thread_Delay; ++int Scope_Thread_Terminate=0; ++struct semaphore Scope_Delay_Event; ++struct timer_list Scope_Timer; ++unsigned long Scope_Hash_Val=1; ++ ++/*===[ Code ]=============================================================*/ ++ ++/*++======================================================================*/ ++void Scope_Init( void ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ INIT_LIST_HEAD( &Scope_List ); ++ init_MUTEX( &Scope_Lock ); ++ init_MUTEX_LOCKED( &Scope_Thread_Delay ); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ++ kernel_thread( Scope_Cleanup_Thread, NULL, 0 ); ++#else ++ kthread_run(Scope_Cleanup_Thread, NULL, "novfs_ST"); ++#endif ++} ++ ++/*++======================================================================*/ ++void Scope_Uninit( void ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ Scope_Thread_Terminate = 1; ++ ++ up(&Scope_Thread_Delay); ++ ++ mb(); ++ while( Scope_Thread_Terminate ) ++ { ++ yield(); ++ } ++ printk( KERN_INFO "Scope_Uninit: Exit\n"); ++ ++} ++ ++/*++======================================================================*/ ++PSCOPE_LIST Scope_Search4Scope( session_t Id, BOOLEAN Session, BOOLEAN Locked ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope, rscope=NULL; ++ struct list_head *sl; ++ int offset; ++ ++ DbgPrint("Scope_Search4Scope: 0x%llx 0x%x 0x%x\n", Id, Session, Locked); ++ ++ if ( Session ) ++ { ++ offset = (int)(&((PSCOPE_LIST)0)->SessionId); ++ } ++ else ++ { ++ offset = (int)(&((PSCOPE_LIST)0)->ScopeId); ++ } ++ ++ if ( !Locked ) ++ { ++ down( &Scope_Lock ); ++ } ++ ++ sl = Scope_List.next; ++ DbgPrint("Scope_Search4Scope: 0x%x\n", sl); ++ while (sl != &Scope_List) ++ { ++ scope = list_entry(sl, SCOPE_LIST, ScopeList); ++ ++ if ( Id == *(session_t *)((char *)scope+offset) ) ++ { ++ rscope = scope; ++ break; ++ } ++ ++ sl = sl->next; ++ } ++ ++ if ( !Locked ) ++ { ++ up( &Scope_Lock ); ++ } ++ ++ DbgPrint("Scope_Search4Scope: return 0x%x\n", rscope); ++ return( rscope ); ++} ++ ++/*++======================================================================*/ ++PSCOPE_LIST Scope_Find_Scope( BOOLEAN Create ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope=NULL, pscope=NULL; ++ task_t *task; ++ scope_t scopeId; ++ int addscope=0; ++ ++ task = current; ++ ++ DbgPrint("Scope_Find_Scope: %d %d %d %d\n", task->uid, task->euid, task->suid, task->fsuid); ++ ++ scopeId = task->euid; ++ ++ scope = Scope_Search4Scope( scopeId, FALSE, FALSE ); ++ ++ if ( !scope && Create ) ++ { ++ scope = Novfs_Malloc( sizeof(*pscope), GFP_KERNEL ); ++ if ( scope ) ++ { ++ scope->ScopeId = scopeId; ++ scope->SessionId = 0; ++ scope->ScopePid = task->pid; ++ scope->ScopeTask = task; ++ scope->ScopeHash = 0; ++ scope->ScopeUid = task->euid; ++ scope->ScopeUserName[0] = '\0'; ++ ++ if ( !Daemon_CreateSessionId( &scope->SessionId ) ) ++ { ++ DbgPrint("Scope_Find_Scope2: %d %d %d %d\n", task->uid, task->euid, task->suid, task->fsuid); ++ memset(scope->ScopeUserName, 0, sizeof(scope->ScopeUserName)); ++ scope->ScopeUserNameLength = 0; ++ Daemon_getpwuid(task->euid, sizeof(scope->ScopeUserName), scope->ScopeUserName); ++ scope->ScopeUserNameLength = strlen(scope->ScopeUserName); ++ addscope = 1; ++ } ++ ++ scope->ScopeHash = Scope_Hash_Val++; ++ DbgPrint("Scope_Find_Scope: Adding 0x%x\n" \ ++ " ScopeId: 0x%llx\n" \ ++ " SessionId: 0x%llx\n" \ ++ " ScopePid: %d\n" \ ++ " ScopeTask: 0x%x\n" \ ++ " ScopeHash: %d\n" \ ++ " ScopeUid: %d\n" \ ++ " ScopeUserNameLength: %d\n" \ ++ " ScopeUserName: %s\n", ++ scope, ++ scope->ScopeId, ++ scope->SessionId, ++ scope->ScopePid, ++ scope->ScopeTask, ++ scope->ScopeHash, ++ scope->ScopeUid, ++ scope->ScopeUserNameLength, ++ scope->ScopeUserName); ++ ++ if ( scope->SessionId ) ++ { ++ down( &Scope_Lock ); ++ list_add(&scope->ScopeList, &Scope_List); ++ up( &Scope_Lock ); ++ } ++ else ++ { ++ Novfs_Free(scope); ++ scope = NULL; ++ } ++ } ++ ++ if (addscope) ++ { ++ Novfs_Add_to_Root( scope->ScopeUserName ); ++ } ++ } ++ ++ return(scope); ++} ++ ++/*++======================================================================*/ ++unsigned long Scope_Get_Hash( PSCOPE_LIST Scope ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ unsigned long hash=0; ++ ++ if ( NULL == Scope) ++ { ++ Scope = Scope_Find_Scope( TRUE ); ++ } ++ ++ if ( Scope && Scope_Validate_Scope( Scope )) ++ { ++ hash = Scope->ScopeHash; ++ } ++ return( hash ); ++} ++ ++/*++======================================================================*/ ++uid_t Scope_Get_Uid( PSCOPE_LIST Scope ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ uid_t uid=0; ++ ++ if ( NULL == Scope) ++ { ++ Scope = Scope_Find_Scope( TRUE ); ++ } ++ ++ if ( Scope && Scope_Validate_Scope( Scope )) ++ { ++ uid = Scope->ScopeUid; ++ } ++ return( uid ); ++} ++ ++/*++======================================================================*/ ++int Scope_Validate_Scope( PSCOPE_LIST Scope ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST s; ++ struct list_head *sl; ++ int retVal = 0; ++ ++ DbgPrint("Scope_Validate_Scope: 0x%x\n", Scope); ++ ++ down( &Scope_Lock ); ++ ++ sl = Scope_List.next; ++ while (sl != &Scope_List) ++ { ++ s = list_entry(sl, SCOPE_LIST, ScopeList); ++ ++ if ( s == Scope ) ++ { ++ retVal = 1; ++ break; ++ } ++ ++ sl = sl->next; ++ } ++ ++ up( &Scope_Lock ); ++ ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++char *Scope_Get_UserName( PSCOPE_LIST Scope ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *name=NULL; ++ ++ if ( !Scope ) ++ { ++ Scope = Scope_Find_Scope( TRUE ); ++ } ++ ++ if ( Scope && Scope_Validate_Scope( Scope )) ++ { ++ name = Scope->ScopeUserName; ++ } ++ return( name ); ++} ++ ++/*++======================================================================*/ ++session_t Scope_Get_SessionId( PSCOPE_LIST Scope ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ session_t sessionId=0; ++ ++ DbgPrint("Scope_Get_SessionId: 0x%p\n", Scope); ++ if ( !Scope ) ++ { ++ Scope = Scope_Find_Scope( TRUE ); ++ } ++ ++ if ( Scope && Scope_Validate_Scope( Scope )) ++ { ++ sessionId = Scope->SessionId; ++ } ++ DbgPrint("Scope_Get_SessionId: return 0x%llx\n", sessionId); ++ return( sessionId ); ++} ++ ++/*++======================================================================*/ ++PSCOPE_LIST Scope_Get_ScopefromName( struct qstr *Name ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope, rscope=NULL; ++ struct list_head *sl; ++ ++ DbgPrint("Scope_Get_ScopefromName: %.*s\n", Name->len, Name->name); ++ ++ down( &Scope_Lock ); ++ ++ sl = Scope_List.next; ++ while (sl != &Scope_List) ++ { ++ scope = list_entry(sl, SCOPE_LIST, ScopeList); ++ ++ if ( (Name->len == scope->ScopeUserNameLength) && ++ (0 == strncmp(scope->ScopeUserName, Name->name, Name->len)) ) ++ { ++ rscope = scope; ++ break; ++ } ++ ++ sl = sl->next; ++ } ++ ++ up( &Scope_Lock ); ++ ++ return( rscope ); ++} ++ ++/*++======================================================================*/ ++int Scope_Set_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope; ++ int retVal=0; ++ ++ scope = Scope_Find_Scope( TRUE ); ++ ++ if ( scope ) ++ { ++ if (TotalSize) scope->ScopeUSize = *TotalSize; ++ if (Free) scope->ScopeUFree = *Free; ++ if (TotalEnties) scope->ScopeUTEnties = *TotalEnties; ++ if (FreeEnties) scope->ScopeUAEnties = *FreeEnties; ++ } ++ ++ ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++int Scope_Get_UserSpace( uint64_t *TotalSize, uint64_t *Free, uint64_t *TotalEnties, uint64_t *FreeEnties ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope; ++ int retVal=0; ++ ++ uint64_t td, fd, te, fe; ++ ++ scope = Scope_Find_Scope( TRUE ); ++ ++ td = fd = te = fe = 0; ++ if ( scope ) ++ { ++ ++ retVal = Daemon_Get_UserSpace(scope->SessionId, &td, &fd, &te, &fe); ++ ++ scope->ScopeUSize = td; ++ scope->ScopeUFree = fd; ++ scope->ScopeUTEnties = te; ++ scope->ScopeUAEnties = fe; ++ } ++ ++ if (TotalSize) *TotalSize = td; ++ if (Free) *Free = fd; ++ if (TotalEnties) *TotalEnties = te; ++ if (FreeEnties) *FreeEnties = fe; ++ ++ return( retVal ); ++} ++ ++/*++======================================================================*/ ++PSCOPE_LIST Scope_Get_ScopefromPath( struct dentry *Dentry ) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope=NULL; ++ char *buf, *path, *cp; ++ struct qstr name; ++ ++ buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); ++ if (buf) ++ { ++ path = Scope_dget_path( Dentry, buf, PATH_LENGTH_BUFFER, 0 ); ++ if (path) ++ { ++ DbgPrint("Scope_Get_ScopefromPath: %s\n", path ); ++ ++ if (*path == '/') path++; ++ ++ cp = path; ++ if ( *cp ) ++ { ++ while ( *cp && (*cp != '/') ) cp++; ++ ++ *cp = '\0'; ++ name.hash = 0; ++ name.len = (int)(cp-path); ++ name.name = path; ++ scope = Scope_Get_ScopefromName( &name ); ++ } ++ } ++ Novfs_Free(buf); ++ } ++ ++ return( scope ); ++} ++ ++/*++======================================================================*/ ++char *add_to_list(char *Name, char *List, char *EndOfList) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ while (*Name && (List < EndOfList) ) ++ { ++ *List++ = *Name++; ++ } ++ ++ if (List < EndOfList) ++ { ++ *List++ = '\0'; ++ } ++ return(List); ++} ++ ++/*++======================================================================*/ ++char *Scope_Get_ScopeUsers() ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope; ++ struct list_head *sl; ++ int asize=8*MAX_USERNAME_LENGTH; ++ char *list, *cp, *ep; ++ ++ DbgPrint("Scope_Get_ScopeUsers\n"); ++ ++ do /* Copy list until done or out of memory */ ++ { ++ list = Novfs_Malloc(asize, GFP_KERNEL); ++ ++ DbgPrint("Scope_Get_ScopeUsers list=0x%p\n", list); ++ if (list) ++ { ++ cp = list; ++ ep = cp+asize; ++ ++ /* ++ * Add the tree and server entries ++ */ ++ cp = add_to_list(TREE_DIRECTORY_NAME, cp, ep); ++ cp = add_to_list(SERVER_DIRECTORY_NAME, cp, ep); ++ ++ down( &Scope_Lock ); ++ ++ sl = Scope_List.next; ++ while ( (sl != &Scope_List) && (cp < ep) ) ++ { ++ scope = list_entry(sl, SCOPE_LIST, ScopeList); ++ ++ DbgPrint("Scope_Get_ScopeUsers found 0x%p %s\n", scope, scope->ScopeUserName); ++ ++ cp = add_to_list(scope->ScopeUserName, cp, ep); ++ ++ sl = sl->next; ++ } ++ ++ up( &Scope_Lock ); ++ ++ if (cp < ep) ++ { ++ *cp++ = '\0'; ++ asize = 0; ++ } ++ else /* Allocation was to small, up size */ ++ { ++ asize *= 4; ++ Novfs_Free(list); ++ list=NULL; ++ } ++ } ++ else /* if allocation fails return an empty list */ ++ { ++ break; ++ } ++ } while ( !list ); /* List was to small try again */ ++ ++ return( list ); ++} ++ ++/*++======================================================================*/ ++void *Scope_Lookup() ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope; ++ ++ scope = Scope_Find_Scope( TRUE ); ++ return( scope ); ++} ++ ++/*++======================================================================*/ ++void ++NO_TRACE ++Scope_Timer_Function(unsigned long Context) ++/* ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ up(&Scope_Thread_Delay); ++} ++ ++/*++======================================================================*/ ++int Scope_Cleanup_Thread(void *Args) ++/* ++ * ++ * Arguments: ++ * ++ * Returns: ++ * ++ * Abstract: ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope, rscope; ++ struct list_head *sl, cleanup; ++ task_t *task; ++ ++ DbgPrint( "Scope_Cleanup_Thread: %d\n", current->pid); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ++ lock_kernel(); ++ snprintf(current->comm, 16, "novfs_ST"); ++ unlock_kernel(); ++ sys_close(0); ++ sys_close(1); ++ sys_close(2); ++#endif ++ ++ /* ++ * Setup and start que timer ++ */ ++ init_timer( &Scope_Timer ); ++ ++ for ( ;; ) ++ { ++ DbgPrint( "Scope_Cleanup_Thread: looping\n"); ++ if ( Scope_Thread_Terminate ) ++ { ++ break; ++ } ++ ++ /* ++ * Check scope list for any terminated processes ++ */ ++ down( &Scope_Lock ); ++ ++ sl = Scope_List.next; ++ INIT_LIST_HEAD( &cleanup ); ++ ++ while (sl != &Scope_List) ++ { ++ scope = list_entry(sl, SCOPE_LIST, ScopeList); ++ sl = sl->next; ++ ++ rscope = NULL; ++ read_lock(&tasklist_lock); ++ for_each_process(task) ++ { ++ if ( (task->uid == scope->ScopeUid) || (task->euid == scope->ScopeUid) ) ++ { ++ rscope = scope; ++ break; ++ } ++ } ++ read_unlock(&tasklist_lock); ++ if ( !rscope ) ++ { ++ list_move( &scope->ScopeList, &cleanup ); ++ DbgPrint("Scope_Cleanup_Thread: Scope=0x%x\n", rscope); ++ } ++ } ++ ++ up(&Scope_Lock); ++ ++ sl = cleanup.next; ++ while ( sl != &cleanup ) ++ { ++ scope = list_entry(sl, SCOPE_LIST, ScopeList); ++ sl = sl->next; ++ ++ DbgPrint("Scope_Cleanup_Thread: Removing 0x%x\n" \ ++ " ScopeId: 0x%llx\n" \ ++ " SessionId: 0x%llx\n" \ ++ " ScopePid: %d\n" \ ++ " ScopeTask: 0x%x\n" \ ++ " ScopeHash: %d\n" \ ++ " ScopeUid: %d\n" \ ++ " ScopeUserName: %s\n", ++ scope, ++ scope->ScopeId, ++ scope->SessionId, ++ scope->ScopePid, ++ scope->ScopeTask, ++ scope->ScopeHash, ++ scope->ScopeUid, ++ scope->ScopeUserName); ++ if ( !Scope_Search4Scope(scope->SessionId, TRUE, FALSE) ) ++ { ++ Novfs_Remove_from_Root( scope->ScopeUserName ); ++ Daemon_DestroySessionId( scope->SessionId ); ++ } ++ Novfs_Free( scope ); ++ } ++ ++ Scope_Timer.expires = jiffies + HZ*CLEANUP_INTERVAL; ++ Scope_Timer.data = (unsigned long)0; ++ Scope_Timer.function = Scope_Timer_Function; ++ add_timer(&Scope_Timer); ++ DbgPrint( "Scope_Cleanup_Thread: sleeping\n"); ++ ++ if (down_interruptible( &Scope_Thread_Delay )) ++ { ++ break; ++ } ++ del_timer(&Scope_Timer); ++ } ++ Scope_Thread_Terminate = 0; ++ ++ printk( KERN_INFO "Scope_Cleanup_Thread: Exit\n"); ++ DbgPrint( "Scope_Cleanup_Thread: Exit\n"); ++ return(0); ++} ++ ++/*++======================================================================*/ ++void Scope_Cleanup( void ) ++/* ++ * ++ * Arguments: None ++ * ++ * Returns: Nothing ++ * ++ * Abstract: Removes all knows scopes. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ PSCOPE_LIST scope; ++ struct list_head *sl; ++ ++ DbgPrint( "Scope_Cleanup:\n"); ++ ++ /* ++ * Check scope list for any terminated processes ++ */ ++ down( &Scope_Lock ); ++ ++ sl = Scope_List.next; ++ ++ while (sl != &Scope_List) ++ { ++ scope = list_entry( sl, SCOPE_LIST, ScopeList ); ++ sl = sl->next; ++ ++ list_del( &scope->ScopeList ); ++ ++ DbgPrint("Scope_Cleanup: Removing 0x%x\n" \ ++ " ScopeId: 0x%llx\n" \ ++ " SessionId: 0x%llx\n" \ ++ " ScopePid: %d\n" \ ++ " ScopeTask: 0x%x\n" \ ++ " ScopeHash: %d\n" \ ++ " ScopeUid: %d\n" \ ++ " ScopeUserName: %s\n", ++ scope, ++ scope->ScopeId, ++ scope->SessionId, ++ scope->ScopePid, ++ scope->ScopeTask, ++ scope->ScopeHash, ++ scope->ScopeUid, ++ scope->ScopeUserName); ++ if ( !Scope_Search4Scope( scope->SessionId, TRUE, TRUE ) ) ++ { ++ Novfs_Remove_from_Root( scope->ScopeUserName ); ++ Daemon_DestroySessionId( scope->SessionId ); ++ } ++ Novfs_Free( scope ); ++ } ++ ++ up(&Scope_Lock); ++ ++} ++ ++/*++======================================================================*/ ++char * ++NO_TRACE ++Scope_dget_path( struct dentry *Dentry, char *Buf, unsigned int Buflen, int Flags) ++/* ++ * Arguments: struct dentry *Dentry - starting entry ++ * char *Buf - pointer to memory buffer ++ * unsigned int Buflen - size of memory buffer ++ * ++ * Returns: pointer to path. ++ * ++ * Abstract: Walks the dentry chain building a path. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ char *retval=&Buf[Buflen]; ++ struct dentry *p=Dentry; ++ int len; ++ ++ *(--retval) = '\0'; ++ Buflen--; ++ ++/* ++ if (!IS_ROOT(p)) ++ { ++ while (Buflen && !IS_ROOT(p)) ++ { ++ if (Buflen > p->d_name.len) ++ { ++ retval -= p->d_name.len; ++ Buflen -= p->d_name.len; ++ memcpy(retval, p->d_name.name, p->d_name.len); ++ *(--retval) = '/'; ++ Buflen--; ++ p = p->d_parent; ++ } ++ else ++ { ++ retval = NULL; ++ break; ++ } ++ } ++ } ++ if (Flags) ++ { ++ len = strlen(p->d_sb->s_type->name); ++ if (Buflen-len > 0) ++ { ++ retval -= len; ++ Buflen -= len; ++ memcpy(retval, p->d_sb->s_type->name, len); ++ *(--retval) = '/'; ++ Buflen--; ++ } ++ } ++ else ++ { ++ *(--retval) = '/'; ++ Buflen--; ++ } ++*/ ++ do ++ { ++ if (Buflen > p->d_name.len) ++ { ++ retval -= p->d_name.len; ++ Buflen -= p->d_name.len; ++ memcpy(retval, p->d_name.name, p->d_name.len); ++ *(--retval) = '/'; ++ Buflen--; ++ p = p->d_parent; ++ } ++ else ++ { ++ retval = NULL; ++ break; ++ } ++ } while (!IS_ROOT(p)); ++ ++ if (IS_ROOT(Dentry)) ++ { ++ retval++; ++ } ++ ++ if (Flags) ++ { ++ len = strlen(p->d_sb->s_type->name); ++ if (Buflen-len > 0) ++ { ++ retval -= len; ++ Buflen -= len; ++ memcpy(retval, p->d_sb->s_type->name, len); ++ *(--retval) = '/'; ++ Buflen--; ++ } ++ } ++ ++ return(retval); ++} ++ ++void Scope_Dump_Tasklist( void ) ++{ ++#ifdef OLD_DEBUG_KERNEL ++ task_t *task; ++ struct files_struct *fs; ++ int i, open_files=0; ++ static char buf[1024]; ++ char *path; ++ ++ ++ for_each_process(task) ++ { ++ kdb_printf("Task List:\n" \ ++ " Task: 0x%p\n" \ ++ " pid: %d\n" \ ++ " tgid: %d\n" \ ++ " uid: %d %d %d %d\n" \ ++ " gid: %d\n" \ ++ " parent: 0x%p\n" \ ++ " comm: %s\n" \ ++ " user: 0x%p\n" \ ++ " real_parent: 0x%p\n" \ ++ " parent_exec_id: 0x%x\n" \ ++ " self_exec_id: 0x%x\n" \ ++ " did_exec: 0x%x\n" \ ++ " signal: 0x%p\n" \ ++ " thread_info: 0x%p\n" \ ++ " security: 0x%p\n", ++ task, ++ task->pid, ++ task->tgid, ++ task->uid,task->euid,task->suid,task->fsuid, ++ task->gid, ++ task->parent, ++ task->comm, ++ task->user, ++ task->real_parent, ++ task->parent_exec_id, ++ task->self_exec_id, ++ task->did_exec, ++ task->signal, ++ task->thread_info, ++ task->security); ++ ++ fs = task->files; ++ kdb_printf(" File List: 0x%p\n", fs); ++ if (fs) ++ { ++ open_files = fs->max_fds; ++ kdb_printf(" Max fds: %d\n", open_files); ++ for (i = 0; ifd[i]; ++ if (f && (f->f_dentry)) ++ { ++ path = Scope_dget_path(f->f_dentry, buf, sizeof(buf), 1); ++ if ( !path ) ++ { ++ path = buf; ++ memcpy(path, f->f_dentry->d_name.name, f->f_dentry->d_name.len); ++ path[f->f_dentry->d_name.len] = '\0'; ++ } ++ kdb_printf(" file(%d): 0x%p\n" \ ++ " f_dentry: 0x%p\n" \ ++ " d_name: %s\n" \ ++ " d_count: %d\n" \ ++ " d_inode: 0x%p\n", ++ i, f, f->f_dentry, path, ++ atomic_read(&f->f_dentry->d_count), ++ f->f_dentry->d_inode); ++ } ++ } ++ } ++ } ++#endif ++} ++ ++void Scope_Dump_Scopetable( void ) ++{ ++#ifdef CONFIG_KDB ++ PSCOPE_LIST scope; ++ struct list_head *sl; ++ ++ sl = Scope_List.next; ++ while (sl != &Scope_List) ++ { ++ scope = list_entry(sl, SCOPE_LIST, ScopeList); ++ sl = sl->next; ++ kdb_printf("Scope List:\n" \ ++ " Scope: 0x%p\n" \ ++ " ScopeId: 0x%llx\n" \ ++ " SessionId: 0x%llx\n" \ ++ " ScopePid: %u\n" \ ++ " ScopeTask: 0x%p\n" \ ++ " ScopeHash: 0x%lx\n" \ ++ " ScopeUid: %ld\n" \ ++ " ScopeUserName: %s\n", ++ scope, ++ scope->ScopeId, ++ scope->SessionId, ++ scope->ScopePid, ++ scope->ScopeTask, ++ scope->ScopeHash, ++ (long)scope->ScopeUid, ++ scope->ScopeUserName); ++ ++ } ++ ++#endif ++} +diff -uNr src.old/src/vfs.h src/src/vfs.h +--- src.old/src/vfs.h 1970-01-01 01:00:00.000000000 +0100 ++++ src/src/vfs.h 2006-10-16 15:08:22.000000000 +0200 +@@ -0,0 +1,283 @@ ++/*++======================================================================== ++ * Program Name: Novell NCP Redirector for Linux ++ * File Name: vfs.h ++ * Version: v1.00 ++ * Author: James Turner ++ * ++ * Abstract: Include module for novfs. ++ * Notes: ++ * Revision History: ++ * ++ * ++ * Copyright (C) 2005 Novell, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ *======================================================================--*/ ++#ifndef __STDC_VERSION__ ++#define __STDC_VERSION__ 0L ++#endif ++ ++/*===[ Include files specific to Linux ]==================================*/ ++#ifdef CONFIG_KDB ++#include ++#include ++ ++#endif /* CONFIG_KDB */ ++ ++#include ++#include ++ ++/*===[ Include files specific to this module ]============================*/ ++ ++/*===[ External data ]====================================================*/ ++extern int Novfs_Version_Major; ++extern int Novfs_Version_Minor; ++extern int Novfs_Version_Sub; ++extern int Novfs_Version_Release; ++ ++/*===[ External prototypes ]==============================================*/ ++extern void *Novfs_Malloc( size_t, int ); ++extern void Novfs_Free( const void * ); ++ ++ ++/*===[ Manifest constants ]===============================================*/ ++#define NOVFS_MAGIC 0x4e574653 ++#define MODULE_NAME "novfs" ++ ++#define UNUSED_VARIABLE(a) (a) = (a) ++ ++#define TREE_DIRECTORY_NAME ".Trees" ++#define SERVER_DIRECTORY_NAME ".Servers" ++ ++#define PATH_LENGTH_BUFFER PATH_MAX ++#define NW_MAX_PATH_LENGTH 255 ++ ++#define IOC_LOGIN 0x4a540000 ++#define IOC_LOGOUT 0x4a540001 ++#define IOC_XPLAT 0x4a540002 ++#define IOC_SESSION 0x4a540003 ++#define IOC_DEBUGPRINT 0x4a540004 ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) ++#define D_CHILD d_u.d_child ++#define AS_TREE_LOCK(l) read_lock_irq(l) ++#define AS_TREE_UNLOCK(l) read_unlock_irq(l) ++#else ++#define D_CHILD d_child ++#define AS_TREE_LOCK(l) spin_lock_irq(l) ++#define AS_TREE_UNLOCK(l) spin_unlock_irq(l) ++#endif ++ ++/* ++ * NetWare file attributes ++ */ ++ ++#define NW_ATTRIBUTE_NORMAL 0x00 ++#define NW_ATTRIBUTE_READ_ONLY 0x01 ++#define NW_ATTRIBUTE_HIDDEN 0x02 ++#define NW_ATTRIBUTE_SYSTEM 0x04 ++#define NW_ATTRIBUTE_EXECUTE_ONLY 0x08 ++#define NW_ATTRIBUTE_DIRECTORY 0x10 ++#define NW_ATTRIBUTE_ARCHIVE 0x20 ++#define NW_ATTRIBUTE_EXECUTE 0x40 ++#define NW_ATTRIBUTE_SHAREABLE 0x80 ++ ++/* ++ * Define READ/WRITE flag for DATA_LIST ++ */ ++#define DLREAD 0 ++#define DLWRITE 1 ++ ++/* ++ * Define list type ++ */ ++#define USER_LIST 1 ++#define SERVER_LIST 2 ++#define VOLUME_LIST 3 ++ ++/* ++ * Define flags used in for inodes ++ */ ++#define USER_INODE 1 ++#define UPDATE_INODE 2 ++ ++/* ++ * Define flags for directory cache flags ++ */ ++#define ENTRY_VALID 0x00000001 ++ ++#ifdef INTENT_MAGIC ++#define NDOPENFLAGS intent.it_flags ++#else ++#define NDOPENFLAGS intent.open.flags ++#endif ++ ++/* ++ * daemon_command_t flags values ++ */ ++#define INTERRUPTIBLE 1 ++ ++#define NO_TRACE __attribute__((__no_instrument_function__)) ++ ++#ifndef NOVFS_VFS_MAJOR ++#define NOVFS_VFS_MAJOR 0 ++#endif ++ ++#ifndef NOVFS_VFS_MINOR ++#define NOVFS_VFS_MINOR 0 ++#endif ++ ++#ifndef NOVFS_VFS_SUB ++#define NOVFS_VFS_SUB 0 ++#endif ++ ++#ifndef NOVFS_VFS_RELEASE ++#define NOVFS_VFS_RELEASE 0 ++#endif ++ ++#define VALUE_TO_STR( value ) #value ++#define DEFINE_TO_STR(value) VALUE_TO_STR(value) ++ ++ ++#define NOVFS_VERSION_STRING \ ++ DEFINE_TO_STR(NOVFS_VFS_MAJOR)"." \ ++ DEFINE_TO_STR(NOVFS_VFS_MINOR)"." \ ++ DEFINE_TO_STR(NOVFS_VFS_SUB)"-" \ ++ DEFINE_TO_STR(NOVFS_VFS_RELEASE) \ ++ "\0" ++ ++/*===[ Type definitions ]=================================================*/ ++typedef struct _ENTRY_INFO ++{ ++ int type; ++ umode_t mode; ++ uid_t uid; ++ gid_t gid; ++ loff_t size; ++ struct timespec atime; ++ struct timespec mtime; ++ struct timespec ctime; ++ int namelength; ++ unsigned char name[1]; ++} ENTRY_INFO, *PENTRY_INFO; ++ ++typedef struct _STRING_ ++{ ++ int Length; ++ unsigned char *Data; ++} STRING, *PSTRING; ++ ++typedef struct _LOGIN_ ++{ ++ STRING Server; ++ STRING UserName; ++ STRING Password; ++} LOGIN, *PLOGIN; ++ ++typedef struct _LOGOUT_ ++{ ++ STRING Server; ++} LOGOUT, *PLOGOUT; ++ ++typedef uint64_t scope_t; ++typedef uint64_t session_t; ++ ++typedef struct _DIR_CACHE_ ++{ ++ struct list_head list; ++ int flags; ++ u64 jiffies; ++ ino_t ino; ++ loff_t size; ++ umode_t mode; ++ struct timespec atime; ++ struct timespec mtime; ++ struct timespec ctime; ++ unsigned long hash; ++ int nameLen; ++ char name[1]; ++} DIR_CACHE, *PDIR_CACHE; ++ ++typedef struct _INODE_DATA_ ++{ ++ void *Scope; ++ unsigned long Flags; ++ struct list_head IList; ++ struct inode *Inode; ++ struct list_head DirCache; ++ struct semaphore DirCacheLock; ++ unsigned long FileHandle; ++ int CacheFlag; ++ char Name[1]; /* Needs to be last entry */ ++} INODE_DATA, *PINODE_DATA; ++ ++typedef struct _DATA_LIST_ ++{ ++ void *page; ++ void *offset; ++ int len; ++ int rwflag; ++} DATA_LIST, *PDATA_LIST; ++ ++typedef struct _XPLAT_ ++{ ++ int xfunction; ++ unsigned long reqLen; ++ void *reqData; ++ unsigned long repLen; ++ void *repData; ++ ++} XPLAT, *PXPLAT; ++ ++ ++/*===[ Function prototypes ]==============================================*/ ++ ++extern int DbgPrint( char *Fmt, ... ); ++extern char *ctime_r(time_t *clock, char *buf); ++ ++ ++/*++======================================================================*/ ++static inline unsigned long InterlockedIncrement( unsigned long *p ) ++/* ++ * ++ * Arguments: unsigned long *p - pointer to value. ++ * ++ * Returns: unsigned long - value prior to increment. ++ * ++ * Abstract: The value of *p is incremented and the value of *p before ++ * it was incremented is returned. This is an atomic operation. ++ * ++ * Notes: ++ * ++ * Environment: ++ * ++ *========================================================================*/ ++{ ++ unsigned long x = 1; ++ ++ mb(); ++ ++#if defined(__i386) || defined(__i386__) ++ __asm__ __volatile__( ++ " lock xadd %0,(%2)" ++ : "+r"(x), "=m"(p) ++ : "r"(p), "m"(p) ++ : "memory"); ++ ++#else ++ x = *p++; ++#endif ++ return( x ); ++} diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-config_h.patch b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-config_h.patch new file mode 100644 index 0000000..98d01e7 --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-config_h.patch @@ -0,0 +1,12 @@ +Index: novfs-2.0.0/src/inode.c +=================================================================== +--- novfs-2.0.0.orig/src/inode.c ++++ novfs-2.0.0/src/inode.c +@@ -29,7 +29,6 @@ + + /*===[ Include files specific to Linux ]==================================*/ + #include +-#include + #include + #include + #include diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch new file mode 100644 index 0000000..4e9d495 --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-dont_use_tasklist_lock.patch @@ -0,0 +1,21 @@ +diff -uNr novfs-1.2.0.orig/novfs/scope.c novfs-1.2.0/novfs/scope.c +--- novfs-1.2.0.orig/src/scope.c 2006-08-30 22:32:57.000000000 +0200 ++++ novfs-1.2.0/src/scope.c 2006-10-15 16:35:47.000000000 +0200 +@@ -869,7 +869,7 @@ + sl = sl->next; + + rscope = NULL; +- read_lock(&tasklist_lock); ++ rcu_read_lock(); + for_each_process(task) + { + if ( (task->uid == scope->ScopeUid) || (task->euid == scope->ScopeUid) ) +@@ -878,7 +878,7 @@ + break; + } + } +- read_unlock(&tasklist_lock); ++ rcu_read_unlock(); + if ( !rscope ) + { + list_move( &scope->ScopeList, &cleanup ); diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-generic_file_read.patch b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-generic_file_read.patch new file mode 100644 index 0000000..85e733c --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-generic_file_read.patch @@ -0,0 +1,22 @@ +Index: novfs-2.0.0/src/inode.c +=================================================================== +--- novfs-2.0.0.orig/src/inode.c ++++ novfs-2.0.0/src/inode.c +@@ -1629,7 +1629,7 @@ ssize_t Novfs_f_read(struct file *file, + !(file->f_flags & O_DIRECT) && + id->CacheFlag ) + { +- totalread = generic_file_read(file, buf, len, off); ++ totalread = do_sync_read(file, buf, len, off); + } + else + { +@@ -1693,7 +1693,7 @@ ssize_t Novfs_f_write(struct file *file, + !(file->f_flags & O_DIRECT) && + id->CacheFlag ) + { +- totalwrite = generic_file_write(file, buf, len, off); ++ totalwrite = do_sync_write(file, buf, len, off); + } + else + { diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-i_blksize.patch b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-i_blksize.patch new file mode 100644 index 0000000..9fdc37e --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-i_blksize.patch @@ -0,0 +1,67 @@ +--- + src/inode.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +Index: novfs-2.0.0/src/inode.c +=================================================================== +--- novfs-2.0.0.orig/src/inode.c ++++ novfs-2.0.0/src/inode.c +@@ -1731,7 +1731,7 @@ ssize_t Novfs_f_write(struct file *file, + if (offset > i_size_read(inode)) + { + i_size_write(inode, offset); +- inode->i_blocks = (offset + inode->i_blksize - 1) >> inode->i_blkbits; ++ inode->i_blocks = (offset + inode->i_sb->s_blocksize - 1) >> inode->i_blkbits; + } + inode->i_mtime = inode->i_atime = CURRENT_TIME; + id->Flags |= UPDATE_INODE; +@@ -2913,12 +2913,12 @@ void update_inode(struct inode *Inode, P + Inode->i_ctime = Info->ctime; + Inode->i_mtime = Info->mtime; + +- if (Inode->i_size && Inode->i_blksize) ++ if (Inode->i_size && Inode->i_sb->s_blocksize) + { + Inode->i_blocks = (u_long)(Info->size >> (loff_t)Inode->i_blkbits); +- Inode->i_bytes = Info->size & (Inode->i_blksize - 1); ++ Inode->i_bytes = Info->size & (Inode->i_sb->s_blocksize - 1); + +- DbgPrint("update_inode: i_blksize=%d\n", Inode->i_blksize); ++ DbgPrint("update_inode: i_blksize=%d\n", Inode->i_sb->s_blocksize); + DbgPrint("update_inode: i_blkbits=%d\n", Inode->i_blkbits); + DbgPrint("update_inode: i_blocks=%d\n", Inode->i_blocks); + DbgPrint("update_inode: i_bytes=%d\n", Inode->i_bytes); +@@ -3604,7 +3604,7 @@ int Novfs_i_getattr(struct vfsmount *mnt + kstat->atime = inode->i_atime; + kstat->mtime = inode->i_mtime; + kstat->ctime = inode->i_ctime; +- kstat->blksize = inode->i_blksize; ++ kstat->blksize = inode->i_sb->s_blocksize; + kstat->blocks = inode->i_blocks; + if (inode->i_bytes) + { +@@ -3909,7 +3909,6 @@ struct inode *Novfs_get_inode(struct sup + inode->i_mode = mode; + inode->i_uid = Uid; + inode->i_gid = 0; +- inode->i_blksize = sb->s_blocksize; + inode->i_blkbits = sb->s_blocksize_bits; + inode->i_blocks = 0; + inode->i_rdev = 0; +@@ -3962,7 +3961,6 @@ struct inode *Novfs_get_inode(struct sup + case S_IFDIR: + inode->i_op = &Novfs_inode_operations; + inode->i_fop = &Novfs_dir_operations; +- inode->i_blksize = 0; + inode->i_blkbits = 0; + break; + +@@ -3973,7 +3971,7 @@ struct inode *Novfs_get_inode(struct sup + + DbgPrint("Novfs_get_inode: size=%lld\n", inode->i_size); + DbgPrint("Novfs_get_inode: mode=0%o\n", inode->i_mode); +- DbgPrint("Novfs_get_inode: i_blksize=%d\n", inode->i_blksize); ++ DbgPrint("Novfs_get_inode: i_blksize=%d\n", inode->i_sb->s_blocksize); + DbgPrint("Novfs_get_inode: i_blkbits=%d\n", inode->i_blkbits); + DbgPrint("Novfs_get_inode: i_blocks=%d\n", inode->i_blocks); + DbgPrint("Novfs_get_inode: i_bytes=%d\n", inode->i_bytes); diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-u.generic_ip.patch b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-u.generic_ip.patch new file mode 100644 index 0000000..827a8a2 --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/files/novell-novfs-2.0.0-u.generic_ip.patch @@ -0,0 +1,609 @@ +--- + src/inode.c | 194 ++++++++++++++++++++++++++++++------------------------------ + 1 file changed, 97 insertions(+), 97 deletions(-) + +Index: novfs-2.0.0/src/inode.c +=================================================================== +--- novfs-2.0.0.orig/src/inode.c ++++ novfs-2.0.0/src/inode.c +@@ -422,9 +422,9 @@ int Novfs_Remove_from_Root(char *RemoveN + dentry = d_lookup( Novfs_root, &name); + if (dentry) + { +- if (dentry->d_inode && dentry->d_inode->u.generic_ip) ++ if (dentry->d_inode && dentry->d_inode->i_private) + { +- ((PINODE_DATA)(dentry->d_inode->u.generic_ip))->Scope = NULL; ++ ((PINODE_DATA)(dentry->d_inode->i_private))->Scope = NULL; + } + dput(dentry); + } +@@ -535,9 +535,9 @@ int Novfs_Add_to_Root2(char *AddName) + inode->i_mtime = CURRENT_TIME; + if ( !Novfs_d_add(Novfs_root, entry, inode, 1)) + { +- if (inode->u.generic_ip) ++ if (inode->i_private) + { +- ((PINODE_DATA)inode->u.generic_ip)->Flags = USER_INODE; ++ ((PINODE_DATA)inode->i_private)->Flags = USER_INODE; + } + PRINT_DENTRY("After Novfs_d_add", entry); + } +@@ -651,7 +651,7 @@ int verify_dentry( struct dentry *dentry + + if ( dentry && dentry->d_parent && + (dir = dentry->d_parent->d_inode) && +- (id = dir->u.generic_ip) ) ++ (id = dir->i_private) ) + { + parent = dget_parent(dentry); + +@@ -675,7 +675,7 @@ int verify_dentry( struct dentry *dentry + /* + * Values don't match so update. + */ +- ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ ((PINODE_DATA)inode->i_private)->Flags |= UPDATE_INODE; + } + + ctime = get_jiffies_64() - ctime; +@@ -776,9 +776,9 @@ int verify_dentry( struct dentry *dentry + id->Flags &= ~UPDATE_INODE; + + dentry->d_inode->i_flags &= ~S_DEAD; +- if (dentry->d_inode->u.generic_ip) ++ if (dentry->d_inode->i_private) + { +- ((PINODE_DATA)dentry->d_inode->u.generic_ip)->Scope = id->Scope; ++ ((PINODE_DATA)dentry->d_inode->i_private)->Scope = id->Scope; + } + } + } +@@ -877,9 +877,9 @@ int Novfs_d_add(struct dentry *Parent, s + Novfs_Free(buf); + } + +- if ( Parent && Parent->d_inode && Parent->d_inode->u.generic_ip) ++ if ( Parent && Parent->d_inode && Parent->d_inode->i_private) + { +- id = (PINODE_DATA)Parent->d_inode->u.generic_ip; ++ id = (PINODE_DATA)Parent->d_inode->i_private; + } + + if (id && id->Scope) +@@ -891,7 +891,7 @@ int Novfs_d_add(struct dentry *Parent, s + scope = Scope_Get_ScopefromPath( d ); + } + +- ((PINODE_DATA)i->u.generic_ip)->Scope = scope; ++ ((PINODE_DATA)i->i_private)->Scope = scope; + + d->d_time = jiffies+(File_update_timeout*HZ); + if (a) +@@ -944,7 +944,7 @@ int Novfs_d_revalidate(struct dentry *de + if ( dentry->d_inode && + dentry->d_parent && + (dir = dentry->d_parent->d_inode) && +- (id = dir->u.generic_ip) ) ++ (id = dir->i_private) ) + { + /* + * Check timer to see if in valid time limit +@@ -1399,15 +1399,15 @@ int Novfs_dir_readdir(struct file * file + { + if (!file->private_data) + { +- if ( inode && inode->u.generic_ip ) ++ if ( inode && inode->i_private ) + { +- sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + if (0 == sessionId) + { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath(file->f_dentry); +- sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ((PINODE_DATA)inode->i_private)->Scope = Scope_Get_ScopefromPath(file->f_dentry); ++ sessionId = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + } +- uid = Scope_Get_Uid(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ uid = Scope_Get_Uid(((PINODE_DATA)inode->i_private)->Scope); + } + else + { +@@ -1501,9 +1501,9 @@ int Novfs_dir_readdir(struct file * file + struct inode *dinode = file->private_data; + PINODE_DATA id = (PINODE_DATA)((char *)file->private_data+sizeof(struct inode)); + +- dinode->u.generic_ip = id; ++ dinode->i_private = id; + +- id->Scope = ((PINODE_DATA)inode->u.generic_ip)->Scope; ++ id->Scope = ((PINODE_DATA)inode->i_private)->Scope; + id->Flags = 0; + INIT_LIST_HEAD( &id->DirCache ); + init_MUTEX( &id->DirCacheLock ); +@@ -1616,7 +1616,7 @@ ssize_t Novfs_f_read(struct file *file, + + if ( file->f_dentry && + (inode = file->f_dentry->d_inode) && +- (id = (PINODE_DATA)inode->u.generic_ip)) ++ (id = (PINODE_DATA)inode->i_private)) + { + + DbgPrint("Novfs_f_read(0x%x 0x%p %d %lld %.*s)\n", +@@ -1685,7 +1685,7 @@ ssize_t Novfs_f_write(struct file *file, + + if ( file->f_dentry && + (inode = file->f_dentry->d_inode) && +- (id = file->f_dentry->d_inode->u.generic_ip) ) ++ (id = file->f_dentry->d_inode->i_private) ) + { + DbgPrint("Novfs_f_write(0x%x %d %lld %.*s)\n", (unsigned long)file->private_data, len, offset, file->f_dentry->d_name.len, file->f_dentry->d_name.name); + +@@ -1844,9 +1844,9 @@ int Novfs_f_open(struct inode *inode, st + DbgPrint("Novfs_f_open: %.*s f_flags=0%o f_mode=0%o i_mode=0%o\n", file->f_dentry->d_name.len, file->f_dentry->d_name.name, file->f_flags, file->f_mode, inode->i_mode); + } + +- if (inode && inode->u.generic_ip) ++ if (inode && inode->i_private) + { +- id = (PINODE_DATA)file->f_dentry->d_inode->u.generic_ip; ++ id = (PINODE_DATA)file->f_dentry->d_inode->i_private; + session = Scope_Get_SessionId(id->Scope); + if (0 == session) + { +@@ -1888,7 +1888,7 @@ int Novfs_f_open(struct inode *inode, st + ino = 0; + if (Novfs_get_entry(dir, &file->f_dentry->d_name, &ino, info)) + { +- ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ ((PINODE_DATA)inode->i_private)->Flags |= UPDATE_INODE; + } + + Novfs_unlock_inode_cache(dir); +@@ -1956,7 +1956,7 @@ int Novfs_f_release(struct inode *inode, + file->f_dentry->d_name.name, + (unsigned long)file->private_data); + +- if ( file->f_dentry->d_inode && (id = file->f_dentry->d_inode->u.generic_ip)) ++ if ( file->f_dentry->d_inode && (id = file->f_dentry->d_inode->i_private)) + { + session = Scope_Get_SessionId(id->Scope); + if (0 == session) +@@ -2109,13 +2109,13 @@ int Novfs_a_writepage(struct page* page, + { + int retCode = -EFAULT; + struct inode *inode = page->mapping->host; +- PINODE_DATA id = inode->u.generic_ip; ++ PINODE_DATA id = inode->i_private; + loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT); + session_t session=0; + DATA_LIST dlst[2]; + size_t len = PAGE_CACHE_SIZE; + +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + + page_cache_get(page); + +@@ -2185,10 +2185,10 @@ int Novfs_a_writepages(struct address_sp + { + DbgPrint(" Inode=0x%x Ino=%d\n", inode, inode->i_ino); + +- if (inode->u.generic_ip) ++ if (inode->i_private) + { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); +- fh = ((PINODE_DATA)inode->u.generic_ip)->FileHandle; ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); ++ fh = ((PINODE_DATA)inode->i_private)->FileHandle; + } + } + +@@ -2427,13 +2427,13 @@ int Novfs_a_readpage(struct file *file, + { + DbgPrint(" Inode=0x%x Ino=%d", inode, inode->i_ino); + +- if (inode->u.generic_ip) ++ if (inode->i_private) + { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ((PINODE_DATA)inode->i_private)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + } + } + } +@@ -2519,13 +2519,13 @@ int Novfs_a_readpages(struct file *file, + { + DbgPrint(" Inode=0x%x Ino=%d\n", inode, inode->i_ino); + +- if (inode->u.generic_ip) ++ if (inode->i_private) + { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ((PINODE_DATA)inode->i_private)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + } + } + } +@@ -2653,13 +2653,13 @@ int Novfs_a_prepare_write(struct file *f + */ + if (file->f_dentry && file->f_dentry->d_inode) + { +- if (file->f_dentry->d_inode->u.generic_ip) ++ if (file->f_dentry->d_inode->i_private) + { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ((PINODE_DATA)inode->i_private)->Scope = Scope_Get_ScopefromPath( file->f_dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + } + } + } +@@ -2741,7 +2741,7 @@ int Novfs_a_commit_write(struct file *fi + size_t len = to - offset; + + DbgPrint("Novfs_a_commit_write: File=0x%p Page=0x%p offset=0x%x To=%u filesize=%lld\n", file, page, offset, to, i_size_read(file->f_dentry->d_inode)); +- if (file->f_dentry->d_inode && (id = file->f_dentry->d_inode->u.generic_ip)) ++ if (file->f_dentry->d_inode && (id = file->f_dentry->d_inode->i_private)) + { + session = Scope_Get_SessionId(id->Scope); + if (0 == session) +@@ -2836,13 +2836,13 @@ int Novfs_i_create(struct inode *dir, st + + if (mode | S_IFREG) + { +- if (dir->u.generic_ip) ++ if (dir->i_private) + { +- session = Scope_Get_SessionId( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId( ((PINODE_DATA)dir->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)dir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)dir->u.generic_ip)->Scope); ++ ((PINODE_DATA)dir->i_private)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)dir->i_private)->Scope); + } + + buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +@@ -2859,7 +2859,7 @@ int Novfs_i_create(struct inode *dir, st + { + if (dentry->d_inode) + { +- ((PINODE_DATA)dentry->d_inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ ((PINODE_DATA)dentry->d_inode->i_private)->Flags |= UPDATE_INODE; + } + } + } +@@ -2951,7 +2951,7 @@ struct dentry * Novfs_i_lookup(struct in + + DbgPrint("Novfs_i_lookup: dir 0x%x %d name %.*s hash %d inode 0x%0p\n", dir, dir->i_ino, dentry->d_name.len, dentry->d_name.name, dentry->d_name.hash, dentry->d_inode); + +- if (dir && (id = dir->u.generic_ip) ) ++ if (dir && (id = dir->i_private) ) + { + retVal = 0; + if ( IS_ROOT( dentry )) +@@ -3066,13 +3066,13 @@ int Novfs_i_unlink(struct inode *dir, st + if ( inode ) + { + DbgPrint("Novfs_i_unlink: dir=0x%x dir->i_ino=%d inode=0x%x ino=%d\n", dir, dir->i_ino, inode, inode->i_ino); +- if (inode->u.generic_ip) ++ if (inode->i_private) + { +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ((PINODE_DATA)inode->i_private)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + } + + buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +@@ -3142,16 +3142,16 @@ int Novfs_i_mkdir(struct inode *dir, str + + mode |= S_IFDIR; + mode &= (S_IFMT | S_IRWXU); +- if ( dir->u.generic_ip ) ++ if ( dir->i_private ) + { +- session = Scope_Get_SessionId( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId( ((PINODE_DATA)dir->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)dir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)dir->u.generic_ip)->Scope); ++ ((PINODE_DATA)dir->i_private)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)dir->i_private)->Scope); + } + +- uid = Scope_Get_Uid( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ uid = Scope_Get_Uid( ((PINODE_DATA)dir->i_private)->Scope); + buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); + if (buf) + { +@@ -3170,7 +3170,7 @@ int Novfs_i_mkdir(struct inode *dir, str + if (inode) + { + update_inode(inode, &info); +- ((PINODE_DATA)inode->u.generic_ip)->Flags &= ~UPDATE_INODE; ++ ((PINODE_DATA)inode->i_private)->Flags &= ~UPDATE_INODE; + + dentry->d_time = jiffies+(File_update_timeout*HZ); + +@@ -3238,9 +3238,9 @@ int Novfs_i_mknod(struct inode *dir, str + return(-EACCES); + } + +- if ( ((PINODE_DATA)dir->u.generic_ip) ) ++ if ( ((PINODE_DATA)dir->i_private) ) + { +- uid = Scope_Get_Uid( ((PINODE_DATA)dir->u.generic_ip)->Scope); ++ uid = Scope_Get_Uid( ((PINODE_DATA)dir->i_private)->Scope); + if (mode & (S_IFREG | S_IFDIR)) + { + inode = Novfs_get_inode(dir->i_sb, mode, dev, uid, 0, &dentry->d_name); +@@ -3344,27 +3344,27 @@ int Novfs_i_rename(struct inode *odir, s + if ( !Novfs_d_strcmp(&newname, &oldname)) + { + +- if ( od->d_inode && od->d_inode->u.generic_ip ) ++ if ( od->d_inode && od->d_inode->i_private ) + { + +- if (nd->d_inode && nd->d_inode->u.generic_ip) ++ if (nd->d_inode && nd->d_inode->i_private) + { +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)ndir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( nd ); +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ ((PINODE_DATA)ndir->i_private)->Scope = Scope_Get_ScopefromPath( nd ); ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->i_private)->Scope); + } + + retCode = Novfs_Delete(newpath, S_ISDIR(nd->d_inode->i_mode), session); + } + + +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)ndir->u.generic_ip)->Scope = Scope_Get_ScopefromPath( nd ); +- session = Scope_Get_SessionId(((PINODE_DATA)ndir->u.generic_ip)->Scope); ++ ((PINODE_DATA)ndir->i_private)->Scope = Scope_Get_ScopefromPath( nd ); ++ session = Scope_Get_SessionId(((PINODE_DATA)ndir->i_private)->Scope); + } + retCode = Novfs_Rename_File( + S_ISDIR(od->d_inode->i_mode), +@@ -3458,13 +3458,13 @@ int Novfs_i_setattr(struct dentry *dentr + return(-EACCES); + } + +- if (inode && inode->u.generic_ip) ++ if (inode && inode->i_private) + { +- session = Scope_Get_SessionId( ((PINODE_DATA)inode->u.generic_ip)->Scope); ++ session = Scope_Get_SessionId( ((PINODE_DATA)inode->i_private)->Scope); + if (0 == session) + { +- ((PINODE_DATA)inode->u.generic_ip)->Scope = Scope_Get_ScopefromPath( dentry ); +- session = Scope_Get_SessionId(((PINODE_DATA)inode->u.generic_ip)->Scope); ++ ((PINODE_DATA)inode->i_private)->Scope = Scope_Get_ScopefromPath( dentry ); ++ session = Scope_Get_SessionId(((PINODE_DATA)inode->i_private)->Scope); + } + + buf = (char *)Novfs_Malloc(PATH_LENGTH_BUFFER, GFP_KERNEL); +@@ -3513,7 +3513,7 @@ int Novfs_i_setattr(struct dentry *dentr + + if ( !(retVal = Novfs_Set_Attr(path, attr, session) ) ) + { +- ((PINODE_DATA)inode->u.generic_ip)->Flags |= UPDATE_INODE; ++ ((PINODE_DATA)inode->i_private)->Flags |= UPDATE_INODE; + + if (ia_valid & ATTR_ATIME) + inode->i_atime = attr->ia_atime; +@@ -3563,7 +3563,7 @@ int Novfs_i_getattr(struct vfsmount *mnt + !IS_ROOT(dentry->d_parent) ) + { + session = 0; +- id = dentry->d_inode->u.generic_ip; ++ id = dentry->d_inode->i_private; + + if (id && (id->Flags & UPDATE_INODE) ) + { +@@ -3744,9 +3744,9 @@ void Novfs_clear_inode(struct inode *ino + { + InodeCount--; + +- if ( inode->u.generic_ip ) ++ if ( inode->i_private ) + { +- PINODE_DATA id=inode->u.generic_ip; ++ PINODE_DATA id=inode->i_private; + + DbgPrint("Novfs_clear_inode: inode=0x%x ino=%d Scope=0x%p Name=%s\n", inode, inode->i_ino, id->Scope, id->Name); + +@@ -3757,8 +3757,8 @@ void Novfs_clear_inode(struct inode *ino + up( &InodeList_lock ); + + +- Novfs_Free(inode->u.generic_ip); +- inode->u.generic_ip = NULL; ++ Novfs_Free(inode->i_private); ++ inode->i_private = NULL; + + remove_inode_hash( inode ); + +@@ -3921,12 +3921,12 @@ struct inode *Novfs_get_inode(struct sup + + DbgPrint("Novfs_get_inode: Inode=0x%p I_ino=%d len=%d\n", inode, inode->i_ino, name->len); + +- if (NULL != (inode->u.generic_ip = Novfs_Malloc(sizeof(INODE_DATA)+name->len, GFP_KERNEL))) ++ if (NULL != (inode->i_private = Novfs_Malloc(sizeof(INODE_DATA)+name->len, GFP_KERNEL))) + { + PINODE_DATA id; +- id = inode->u.generic_ip; ++ id = inode->i_private; + +- DbgPrint("Novfs_get_inode: u.generic_ip 0x%p\n", id); ++ DbgPrint("Novfs_get_inode: i_private 0x%p\n", id); + + id->Scope = NULL; + id->Flags = 0; +@@ -4343,7 +4343,7 @@ int Novfs_lock_inode_cache( struct inode + int retVal = 0; + + DbgPrint("Novfs_lock_inode_cache: 0x%p\n", i); +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + down( &id->DirCacheLock ); + retVal = 1; +@@ -4369,7 +4369,7 @@ void Novfs_unlock_inode_cache( struct in + { + PINODE_DATA id; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + up( &id->DirCacheLock ); + } +@@ -4397,7 +4397,7 @@ int Novfs_enumerate_inode_cache( struct + int retVal = -1; + + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + if ( (NULL == iteration) || (NULL == *iteration) ) + { +@@ -4456,7 +4456,7 @@ int Novfs_get_entry( struct inode *i, st + char *n=""; + int nl=6; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + if (name && name->len) + { +@@ -4545,7 +4545,7 @@ int Novfs_get_entry_time( struct inode * + char *n=""; + int nl=6; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + if (name && name->len) + { +@@ -4605,7 +4605,7 @@ int Novfs_get_remove_entry( struct inode + int retVal = -1; + + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + l = id->DirCache.next; + +@@ -4653,7 +4653,7 @@ void Novfs_invalidate_inode_cache( struc + PDIR_CACHE dc; + struct list_head *l; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + list_for_each(l, &id->DirCache) + { +@@ -4690,7 +4690,7 @@ PDIR_CACHE Novfs_lookup_inode_cache( str + int nl=6; + int hash=0; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + if (name && name->name) + { +@@ -4768,7 +4768,7 @@ int Novfs_lookup_validate( struct inode + char *n=""; + int nl=6; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + if (name && name->len) + { +@@ -4815,7 +4815,7 @@ int Novfs_add_inode_entry( + PDIR_CACHE new; + int retVal = -ENOMEM; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + new = Novfs_Malloc(sizeof(DIR_CACHE)+name->len, GFP_KERNEL); + if (new) +@@ -4888,7 +4888,7 @@ int Novfs_update_entry( struct inode *i, + char mtime_buf[32]; + char ctime_buf[32]; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + + if (name && name->len) +@@ -4966,7 +4966,7 @@ void Novfs_remove_inode_entry( struct in + char *n=""; + int nl=6; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + dc = Novfs_lookup_inode_cache( i, name, ino ); + if (dc) +@@ -5015,7 +5015,7 @@ void Novfs_free_invalid_entries( struct + PDIR_CACHE dc; + struct list_head *l; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + list_for_each( l, &id->DirCache ) + { +@@ -5057,7 +5057,7 @@ void Novfs_free_inode_cache( struct inod + PDIR_CACHE dc; + struct list_head *l; + +- if ( i && (id = i->u.generic_ip) && id->DirCache.next ) ++ if ( i && (id = i->i_private) && id->DirCache.next ) + { + list_for_each( l, &id->DirCache ) + { +@@ -5109,7 +5109,7 @@ Novfs_dump_inode_cache(int argc, const c + kdb_printf("Inode: 0x%p\n", inode); + if (inode) + { +- id = inode->u.generic_ip; ++ id = inode->i_private; + kdb_printf("INODE_DATA: 0x%p\n", id); + + if ( id && id->DirCache.next ) diff --git a/trunk/novell4gentoo/net-fs/novell-novfs/novell-novfs-2.0.0_p2.ebuild b/trunk/novell4gentoo/net-fs/novell-novfs/novell-novfs-2.0.0_p2.ebuild new file mode 100644 index 0000000..0998ce4 --- /dev/null +++ b/trunk/novell4gentoo/net-fs/novell-novfs/novell-novfs-2.0.0_p2.ebuild @@ -0,0 +1,59 @@ +# Copyright 1999-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +inherit eutils rpm linux-mod + +MY_PV="${PV/_p/-}" + +DESCRIPTION="Novell Client for Linux Filesystem" +HOMEPAGE="http://www.novell.com" +SRC_URI="http://${NOVELL_ACCOUNT_USERNAME}:${NOVELL_ACCOUNT_PASSWORD}@cdn.novell.com/prot/2JyMn7sWP_Q~/novell-client-1.2-SLE10.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~x86 ~amd64" +IUSE="" + +DEPEND="" + +RDEPEND="virtual/linux-sources + !net-misc/novell-novfs" + +RESTRICT="nomirror" + +BUILD_PARAMS="-C $KERNEL_DIR SUBDIRS=${WORKDIR}/${PN}-${MY_PV}/opt/novell/ncl/src/src" +MODULE_NAMES="novfs(novfs:${WORKDIR}/${PN}-${MY_PV}/opt/novell/ncl/src/src:${WORKDIR}/${PN}-${MY_PV}/opt/novell/ncl/src/src" +BUILD_TARGETS="modules" +MODULESD_NOVFS_ENABLED="" + +src_unpack() { + unpack ${A} + mkdir -p ${WORKDIR}/${PN}-${MY_PV} + cd ${PN}-${MY_PV} + rpm_unpack ${WORKDIR}/ncl_build_711/NCL_disk/novell/i586/${PN}-1.2.0-17.i586.rpm + cd ${WORKDIR}/${PN}-${MY_PV}/opt/novell/ncl/src + epatch ${FILESDIR}/novell-novfs-1.2.0_to_2.0.0.patch + epatch ${FILESDIR}/novell-novfs-2.0.0-config_h.patch + epatch ${FILESDIR}/novell-novfs-2.0.0-generic_file_read.patch + epatch ${FILESDIR}/novell-novfs-2.0.0-i_blksize.patch + epatch ${FILESDIR}/novell-novfs-2.0.0-u.generic_ip.patch + epatch ${FILESDIR}/novell-novfs-2.0.0-dont_use_tasklist_lock.patch +} + +src_compile() { + linux-mod_src_compile +} + +src_install() { + linux-mod_src_install + generate_modulesd +} + +pkg_postinst() { + linux-mod_pkg_postinst +} + +pkg_postrm() { + linux-mod_pkg_postrm +}