Re: gdbm licence issue
On Mon, Feb 23, 2004 at 10:53:39PM +0100, Sander Striker wrote: On Mon, 2004-02-23 at 22:25, Jim Jagielski wrote: Joe Orton wrote: Bringing this up in the appropriate forum. IANAL, but... gdbm is licensed under the GNU GPL. apr_dbm_gdbm.c uses the GDBM interface, hence is a work based on GDBM, hence all of apr-util must be redistributed only under the terms of the GPL. We just use the gdbm API, don't we? As such, I don't think that GPL applies. If it did, wouldn't PHP/Perl/Python, etc all need to be re-distributed under GPL? We don't require it, but instead allow it to be used if available. If a 3rd party takes APR and compiles it so it *requires/uses* gdbm, then GPL kicks in. After all, we aren't redistributing it. This is my understanding aswell. Same here, but would love to have my understanding corrected, if it is a problem. Cheers, -g -- Greg Stein, http://www.lyra.org/
Re: Compile-time vs. run-time checks
On Feb 23, 2004, at 1:43 PM, Greg Stein wrote: On Mon, Feb 23, 2004 at 01:33:31PM -0600, Scott Lamb wrote: I'm putting together a patch to use SO_(RCV|SND)TIMEO for apr_socket_timeout where available; I expect I'll find it has better performance on some platforms, as it would no longer require using non-blocking IO and preceding every read() and write() with a select(). (I intend to try benchmarking Apache on Darwin, where the system call overhead seems to be quite high.) It seems I was way off...I've got my somewhat tested but unpolished patch attached, but unless someone else runs benchmarks and sees a speedup, I see no real reason to apply. I couldn't see a statistically significant difference between them. In transferring either big or small files with httpd-2.0 HEAD and ab over loopback on Darwin (keepalive on). Which I'd think would be the ideal situation for seeing an improvement... I'm surprised. System calls seem to be an order of magnitude slower on Darwin than they were on Linux for roughly comparable hardware, so I'd expected to see the extra overhead being significant in some way. But I guess it was just such a small piece of the whole that it didn't matter anyway. Or something. On some older versions of platforms (Linux 2.2), these #defines exist but do not work - it's not possible to set them. Can I assume that if APR is built with a kernel in which it does work (Linux 2.4), it will be run with one as well? Or should I include a runtime check for this option? Icky. I don't think it is really possible to make that assumption. Thankfully, I also believe this is reasonably solved with a global variable (i.e. race conditions around coming up with the same flag don't apply :-), and the value certainly won't change over the process' lifetime). I would recommend a dynamic solution for now. We may be able to make that compile-time for certain platforms, where we know all versions handle the flag properly [when present]. Thanks for the suggestion. Maybe I'll apply it to the next patch. :/ Cheers, -g Scott apr-timeout.patch Description: Binary data
Re: gdbm licence issue
--On Monday, February 23, 2004 5:04 PM -0800 Greg Stein [EMAIL PROTECTED] wrote: Same here, but would love to have my understanding corrected, if it is a problem. Well, if we believe the AL v2.0 is GPL-compatible, then this is a moot point, I believe. We're not distributing GDBM (which would be against ASF policy), but our license *is* GPL-compatible (mainly because we say it is). However, AIUI, note that when GDBM is linked in, *all* of httpd falls under the GPL. *shrug* /me waits for Roy's cluebat of wisdom (+1000) to descend upon me My head hurts thinking about this. And, I could very well be wrong. But, I wouldn't remove the code from our repository just yet. -- justin
RESEND: Deficiencies in the poll and/or socket APIs
[ Resending, as there's been no discussion, and I'm afraid it may have been missed. I need an answer soon. Thanks :) ] I'm considering moving my application to APR over my own internal utility library (APR is much nicer), so I've started implementing a simple descriptor event loop to get a feel for it. However, I've run up against a couple of deficiencies in the API and I'm not sure where to go from here. I'm working with APR 0.9.4. I'm only working off the headers to know what's possible, so if there's an obvious piece of documentation somewhere that I've missed, please just point me there. 1. I don't see a way to update the requested events for a fd that is already in a pollset. I can update pollfd-reqevents, but those changes never make it to the underlying pollfd structure (Unix). It seems the only way to do this is to call pollset_remove(), then pollset_add() again. This is obviously suboptimal, as pollset_remove() does a search. pollset_remove() could be optimised if an index into the pollfd array was held in apr_pollfd_t (or something similar, as this is platform-dependent). We'd lose the ability to store a single descriptor in a pollset twice, but it would get rid of the search, which would make the addition of a new function to update the underlying pollfd trivial (no search required). 2. I need to be able to figure out when a socket has been closed by the peer. The usual way to do this is to check how many bytes are waiting to be read when the socket goes readable. I've used both the FIONREAD ioctl and the MSG_PEEK flag to recv before to do this. It doesn't seem that the APR socket API supports any mechanism like this. Getting a POLLHUP event from the poll call also seems to work in some places, but its not really portable[1], and APR does it differently again. It would be easy to add a call to the socket API to get the number of bytes waiting, but there may not be equivalent functions available on non-Unix platforms. So, where do people suggest I go from here? I'm happy to implement any/all of this, and submit patches, I just want to make sure I'm going down the right path before I start. Please let me know what the best course of action is here. Regards, Rob. [1] http://www.greenend.org.uk/rjk/2001/06/poll.html -- Robert Norris GPG: 1024D/FC18E6C2 Email+Jabber: [EMAIL PROTECTED]Web: http://cataclysm.cx/ signature.asc Description: Digital signature
Re: Compile-time vs. run-time checks
On Mon, 23 Feb 2004, Scott Lamb wrote: significant difference between them. In transferring either big or small files with httpd-2.0 HEAD and ab over loopback on Darwin (keepalive on). Which I'd think would be the ideal situation for seeing an improvement... Neither ab nor loopback make for a particularly good test of this sort of thing. I suggest you use flood instead of ab and use two machines instead of the loopback adapter. --Cliff
Re: gdbm licence issue
On Mon, 23 Feb 2004, Justin Erenkrantz wrote: Well, if we believe the AL v2.0 is GPL-compatible, then this is a moot point, I believe. GPL-compatible means that Apache-licensed code can be added to a GPL product and that that product can still be distributed under the GPL, not the other way around. --Cliff
apr_socket_timeout speed (was Re: Compile-time vs. run-time checks)
On Feb 23, 2004, at 11:11 PM, Cliff Woolley wrote: On Mon, 23 Feb 2004, Scott Lamb wrote: significant difference between them. In transferring either big or small files with httpd-2.0 HEAD and ab over loopback on Darwin (keepalive on). Which I'd think would be the ideal situation for seeing an improvement... Neither ab nor loopback make for a particularly good test of this sort of thing. I suggest you use flood instead of ab and use two machines instead of the loopback adapter. I'll play with it a while. Flood was giving me trouble (couldn't find docs on what the numbers it spat out meant, and the analysis awk script got divide-by-zero errors), so I tried siege for a bit. Had disappointing results, then realized I wasn't anywhere close to saturating the server's CPU or the network. The roughly equal-speed Linux 2.6 client machine is groaning...and it's spending 60% time in softirq, according to top. I recently replaced the network card with some cheap thing; maybe the drivers are just that awful. If so, I'll need to replace it before getting decent benchmarks; it might be a while. --Cliff Thanks for the ideas. Scott
Re: gdbm licence issue
On Mon, Feb 23, 2004 at 04:25:41PM -0500, Jim Jagielski wrote: Joe Orton wrote: Bringing this up in the appropriate forum. IANAL, but... gdbm is licensed under the GNU GPL. apr_dbm_gdbm.c uses the GDBM interface, hence is a work based on GDBM, hence all of apr-util must be redistributed only under the terms of the GPL. We just use the gdbm API, don't we? As such, I don't think that GPL applies. Use of the API is usually interpreted as forming a derivative work under copyright law, and I'm certain it's the FSF's interpretation, which is what counts here. C'mon, think about it: if you could link random bits of code against a library licensed under the GPL without forming a derivative work, the GPL would be fairly pointless and certainly not very viral as everyone gets so upset about. joe
Re: gdbm licence issue
On Mon, Feb 23, 2004 at 08:10:33PM -0800, Justin Erenkrantz wrote: --On Monday, February 23, 2004 5:04 PM -0800 Greg Stein [EMAIL PROTECTED] wrote: Same here, but would love to have my understanding corrected, if it is a problem. Well, if we believe the AL v2.0 is GPL-compatible, then this is a moot point, I believe. We're not distributing GDBM (which would be against ASF policy), but our license *is* GPL-compatible (mainly because we say it is). However, AIUI, note that when GDBM is linked in, *all* of httpd falls under the GPL. *shrug* Since apr_dbm_gdbm.c is a derivative work of GDBM, the GPL imposes restrictions on redistribution of apr_dbm_gdbm.c (if not all of apr-util): this is true regardless of whether or not GDBM is redistributed alongside apr-util. GPL clause 2(b) is pretty clear: 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. The only question in my mind is whether or not apr_dbm_gdbm.c is a derivative work of GDBM. I think the filename alone gives a pretty strong clue: and unless we want to get Genuine Legal Advice to the contrary, we must default to the presumption that it is a derivative work. Given that fact, it is: 1. undesirable to redistribute apr_dbm_gdbm.c since it imposes more restrictive licensing conditions on the code, and more seriously: 2. a violation of the GDBM copyright to redistribute apr_dbm_gdbm.c under the terms of the ALv2, since the FSF considers the ALv2 to impose extra restrictions beyond that of the GPL. (and it's the FSF's opinion that counts) joe
Re: gdbm licence issue
On Tue, Feb 24, 2004 at 10:30:19AM +, Joe Orton wrote: Well, if we believe the AL v2.0 is GPL-compatible, then this is a moot point, I believe. We're not distributing GDBM (which would be against ASF policy), but our license *is* GPL-compatible (mainly because we say it is). However, AIUI, note that when GDBM is linked in, *all* of httpd falls under the GPL. *shrug* Since apr_dbm_gdbm.c is a derivative work of GDBM, the GPL imposes restrictions on redistribution of apr_dbm_gdbm.c (if not all of apr-util): this is true regardless of whether or not GDBM is redistributed alongside apr-util. GPL clause 2(b) is pretty clear: 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. The only question in my mind is whether or not apr_dbm_gdbm.c is a derivative work of GDBM. I think the filename alone gives a pretty strong clue: and unless we want to get Genuine Legal Advice to the contrary, we must default to the presumption that it is a derivative work. Based on everything I've read on the FSF website, I'm sure it thinks this file is indeed a derivative work. In my opinion, observing its wishes with regard to its own software is important regardless of what we must do, legally. Furthermore, since this is a library designed for eventual use in a wide variety of programs, free and proprietary, is easy GDBM support worth the associating this sort of license uncertainty with the software? Given that fact, it is: 1. undesirable to redistribute apr_dbm_gdbm.c since it imposes more restrictive licensing conditions on the code, and more seriously: 2. a violation of the GDBM copyright to redistribute apr_dbm_gdbm.c under the terms of the ALv2, since the FSF considers the ALv2 to impose extra restrictions beyond that of the GPL. (and it's the FSF's opinion that counts) joe How about one of these options? (a) Remove GDBM support. (b) Only include GDBM support if the installing user passes --enable-gdbm and --enable-gpl to configure (passing only the former would elicit an error). This ensures that the installer accepts further distribution under the GPL. (c) Split GDBM support off in the form of a patch and post it somewhere convenient but separate from the source. (d) Split GDBM support off in the form of a patch and include that patch in the source tree. Users can then actively choose to apply it and build a GPL'ed apr. Note that only options (a) and (c) technically allow us to distribute the source tarball under any terms other than those of the GPL. However, other software packages Jim mentioned, such as Perl, don't get that pure, so I don't think the other options are terribly problematic. I like (b), personally, and will code it if asked. -Noah
Re: gdbm licence issue
Noah Misch wrote: The only question in my mind is whether or not apr_dbm_gdbm.c is a derivative work of GDBM. I think the filename alone gives a pretty strong clue: and unless we want to get Genuine Legal Advice to the contrary, we must default to the presumption that it is a derivative work. Based on everything I've read on the FSF website, I'm sure it thinks this file is indeed a derivative work. In my opinion, observing its wishes with regard to its own software is important regardless of what we must do, legally. Furthermore, since this is a library designed for eventual use in a wide variety of programs, free and proprietary, is easy GDBM support worth the associating this sort of license uncertainty with the software? If the simple fact of having completely optional support for gdbm and writing a code fragment which utilizes the API of gdbm and the fact that the *name* of the file says this is the APR dbm interface for gdbm means that the code is now a derivative work, APU is one of many many many non-compliant efforts out there. We don't require gdbm, we don't redistribute it, and it's not our preferred implementation (sdbm is). I think we should simply ask FSF directly. If it is, then the Perl/PHP/Python/OpenLDAP, etc... guys would like to know as well I think. -- === Jim Jagielski [|] [EMAIL PROTECTED] [|] http://www.jaguNET.com/ A society that will trade a little liberty for a little order will lose both and deserve neither - T.Jefferson
Re: gdbm licence issue
On Tue, 2004-02-24 at 15:35, Jim Jagielski wrote: Noah Misch wrote: The only question in my mind is whether or not apr_dbm_gdbm.c is a derivative work of GDBM. I think the filename alone gives a pretty strong clue: and unless we want to get Genuine Legal Advice to the contrary, we must default to the presumption that it is a derivative work. Based on everything I've read on the FSF website, I'm sure it thinks this file is indeed a derivative work. In my opinion, observing its wishes with regard to its own software is important regardless of what we must do, legally. Furthermore, since this is a library designed for eventual use in a wide variety of programs, free and proprietary, is easy GDBM support worth the associating this sort of license uncertainty with the software? If the simple fact of having completely optional support for gdbm and writing a code fragment which utilizes the API of gdbm and the fact that the *name* of the file says this is the APR dbm interface for gdbm means that the code is now a derivative work, APU is one of many many many non-compliant efforts out there. We don't require gdbm, we don't redistribute it, and it's not our preferred implementation (sdbm is). I think we should simply ask FSF directly. If it is, then the Perl/PHP/Python/OpenLDAP, etc... guys would like to know as well I think. +1. Sander
Re: RESEND: Deficiencies in the poll and/or socket APIs
Robert Norris wrote: [ Resending, as there's been no discussion, and I'm afraid it may have been missed. I need an answer soon. Thanks :) ] Greg Ames and I are working on an Apache 2.0 patch to do keep-alive reads in an event-loop (to free up threads blocked on keep-alive connections). I expect we will run into some of what you are now observing and dig into the code and learn it in detail. My comments that follow are just a little more reliable than speculation... (and if someone wants to step in with definitive answers, please do so...). I'm considering moving my application to APR over my own internal utility library (APR is much nicer), so I've started implementing a simple descriptor event loop to get a feel for it. However, I've run up against a couple of deficiencies in the API and I'm not sure where to go from here. I'm working with APR 0.9.4. I'm only working off the headers to know what's possible, so if there's an obvious piece of documentation somewhere that I've missed, please just point me there. 1. I don't see a way to update the requested events for a fd that is already in a pollset. I can update pollfd-reqevents, but those changes never make it to the underlying pollfd structure (Unix). It seems the only way to do this is to call pollset_remove(), then pollset_add() again. This is obviously suboptimal, as pollset_remove() does a search. I think your observation is correct on both counts. The pollset API is basically a first cut implementation and I would expect optimizations like you describe would not be in the implementation. pollset_remove() could be optimised if an index into the pollfd array was held in apr_pollfd_t (or something similar, as this is platform-dependent). We'd lose the ability to store a single descriptor in a pollset twice, I am not sure the ability to store a single descriptor twice is an issue. A pollfd array would need to be dynamically sizeable. We would not want to place artificial limits on the number of fs's in the pollset (unlike the array passed in to select() for example). but it would get rid of the search, which would make the addition of a new function to update the underlying pollfd trivial (no search required). 2. I need to be able to figure out when a socket has been closed by the peer. The usual way to do this is to check how many bytes are waiting to be read when the socket goes readable. I've used both the FIONREAD ioctl and the MSG_PEEK flag to recv before to do this. It doesn't seem that the APR socket API supports any mechanism like this. I think that is correct. The biggest user of APR (Apache 2.0) just does a read when the socket goes readable. Either the read works and there are bytes to handle, or it fails because the client close'd its end of the connection. Getting a POLLHUP event from the poll call also seems to work in some places, but its not really portable[1], and APR does it differently again. I agree this is not portable. Bill
Re: gdbm licence issue
--On Tuesday, February 24, 2004 12:37 PM -0500 Jeff Trawick [EMAIL PROTECTED] wrote: Perhaps the default build should disable any features which could make the licensing of the generated product different than the licensing of the source code, and if the user is happy otherwise then they can enable such features? What I have done thus far where this has been a potential issue is to add --without-gdbm --without-berkeley-db to the configure invocation. That'd be fair, I think. BTW, what's the issue with BDB's license? -- justin
Re: gdbm licence issue
Jeff Trawick wrote: Perhaps the default build should disable any features which could make the licensing of the generated product different than the licensing of the source code, and if the user is happy otherwise then they can enable such features? What I have done thus far where this has been a potential issue is to add --without-gdbm --without-berkeley-db to the configure invocation. +1... Including in sensitive libs should be a specifically requested user action. -- === Jim Jagielski [|] [EMAIL PROTECTED] [|] http://www.jaguNET.com/ A society that will trade a little liberty for a little order will lose both and deserve neither - T.Jefferson
Re: gdbm licence issue
Justin Erenkrantz wrote: --On Tuesday, February 24, 2004 12:37 PM -0500 Jeff Trawick [EMAIL PROTECTED] wrote: Perhaps the default build should disable any features which could make the licensing of the generated product different than the licensing of the source code, and if the user is happy otherwise then they can enable such features? What I have done thus far where this has been a potential issue is to add --without-gdbm --without-berkeley-db to the configure invocation. That'd be fair, I think. BTW, what's the issue with BDB's license? -- justin Actually there were other reasons that Berkeley db support was disabled, so that was a bad example :( IANAL, but I'm pretty sure that there are no requirements placed on you by merely using the Berkeley db libraries already installed on the end-user's system. Bundling Berkeley db support in a product would be a completely different issue however, and would require either licensing fees to be paid or source code of the product to be published. But none of this issue with Berkeley db seems to be apr's problem.
Re: gdbm licence issue
On Tue, Feb 24, 2004 at 08:46:53AM -0800, Justin Erenkrantz wrote: --On Tuesday, February 24, 2004 10:30 AM + Joe Orton [EMAIL PROTECTED] wrote: 2. a violation of the GDBM copyright to redistribute apr_dbm_gdbm.c under the terms of the ALv2, since the FSF considers the ALv2 to impose extra restrictions beyond that of the GPL. (and it's the FSF's opinion that counts) I'm not sure how you view apr_dbm_gdbm.c as a derivative work of GDBM. Is it the fact that it calls some C functions qualifies as a derivative work? Well the more I think about it the more clear-cut it gets :) apr_dbm_gdbm.c is based on GDBM: it is derived from the GDBM source code (gdbm.h), it will not compile without GDBM, it does not exist except to be used with GDBM. It is no mere coincidence that the symbols match up, and that when you compile the file it actually does something useful. I'm a bit surprised this is a contentious issue: this is how the GPL is and always has been interpreted. It is illegal to redistribute modules for the Linux kernel except under the terms of the GPL because such modules are derived works of the Linux kernel by virtue of using its interfaces. This is no different. Yes, the fact of apr-util *linking* to GDBM causes the entire work to be GPLd (as it is derived from GDBM), but we don't distribute it that way yet doing so is not a violation of the AL v2.0. Please read: http://www.apache.org/licenses/GPL-compatibility.html I know it's the ASF position that the GPL is compatible with the AL v2, I don't want to get into that argument. The issue is that the FSF, which is both the copyright holder of GDBM and author of the GPL, apparently considers the two licenses to be incompatible. Is the responsible thing for us to do to blithely ignore the opinion of the copyright holder? I can't imagine so. Regards, joe
Re: gdbm licence issue
On Tue, 2004-02-24 at 20:54, Joe Orton wrote: I'm not sure how you view apr_dbm_gdbm.c as a derivative work of GDBM. Is it the fact that it calls some C functions qualifies as a derivative work? Well the more I think about it the more clear-cut it gets :) apr_dbm_gdbm.c is based on GDBM: it is derived from the GDBM source code (gdbm.h), it will not compile without GDBM, it does not exist except to be used with GDBM. It is no mere coincidence that the symbols match up, and that when you compile the file it actually does something useful. This would make the use of any OS header files a derived work of the OS, I can't imagine you think this is the case. I'm a bit surprised this is a contentious issue: this is how the GPL is and always has been interpreted. It is illegal to redistribute modules for the Linux kernel except under the terms of the GPL because such modules are derived works of the Linux kernel by virtue of using its interfaces. This is no different. Huh? So how do you explain the existence of propietary modules, the ones that once loaded make a certain 'tainted' keyword appear? Sander
Re: gdbm licence issue
On Tue, 24 Feb 2004, Sander Striker wrote: This would make the use of any OS header files a derived work of the OS, I can't imagine you think this is the case. Not a good example; there's a specific exemption for that case IIRC. --Cliff
Re: gdbm licence issue
--On Tuesday, February 24, 2004 1:35 PM -0800 Greg Stein [EMAIL PROTECTED] wrote: I'll write to the FSF and get their position on the matter. As mentioned earlier, the answer would apply not only to APRUTIL, but to Python and Perl, too (plus N other projects). FWIW, Manoj pointed this out to me this morning. -- justin http://www.artifex.com/downloads/gs/doc/Make.htm#GNU_readline However, even though the GPL allows linking GPLed code (such as the GNU readline library package) with non-GPLed code (such as all the rest of AFPL Ghostscript) if one doesn't distribute the result, the Free Software Foundation, creators of the GPL, have told us that in their opinion, the GPL forbids distributing non-GPLed code that is merely intended to be linked with GPLed code. We understand that FSF takes this position in order to prevent the construction of software that is partly GPLed and partly not GPLed, even though the text of the GPL does not actually forbid this (it only forbids distribution of such software). We think that FSF's position is legally questionable and not in the best interest of users, but we do not have the resources to challenge it, especially since FSF's attorney apparently supports it.
Re: RESEND: Deficiencies in the poll and/or socket APIs
On Tue, Feb 24, 2004 at 09:39:01AM -0500, Bill Stoddard wrote: Greg Ames and I are working on an Apache 2.0 patch to do keep-alive reads in an event-loop (to free up threads blocked on keep-alive connections). I expect we will run into some of what you are now observing and dig into the code and learn it in detail. I've already done some digging into the poll code, and it seems pretty straightforward. Let me know if you'd like to work together on that piece so we can make sure that there's enough pieces in place to support both Apache and a more traditional persistent-connection server. pollset_remove() could be optimised if an index into the pollfd array was held in apr_pollfd_t (or something similar, as this is platform-dependent). We'd lose the ability to store a single descriptor in a pollset twice, I am not sure the ability to store a single descriptor twice is an issue. A pollfd array would need to be dynamically sizeable. We would not want to place artificial limits on the number of fs's in the pollset (unlike the array passed in to select() for example). Absolutely, we don't want to place limits on the pollset if not necessary. My point was that if we maintained a pointer to a descriptors' location in the set, then we can't have the same descriptor in the set more than once (unless we keep track of all of them, but I can't see why you'd actually want the same descriptor in the set more than once anyway). 2. I need to be able to figure out when a socket has been closed by the peer. The usual way to do this is to check how many bytes are waiting to be read when the socket goes readable. I've used both the FIONREAD ioctl and the MSG_PEEK flag to recv before to do this. It doesn't seem that the APR socket API supports any mechanism like this. I think that is correct. The biggest user of APR (Apache 2.0) just does a read when the socket goes readable. Either the read works and there are bytes to handle, or it fails because the client close'd its end of the connection. It seems to me (as long as non-UNIX platforms have a mechanism to support it) that it would be dead simple to provide a function that does a FIONREAD and returns the number. Apache wouldn't even have to bother with it. Getting a POLLHUP event from the poll call also seems to work in some places, but its not really portable[1], and APR does it differently again. I agree this is not portable. Is anyone aware of another commonly-used method to detect a closed socket? Anyway, this is enough confirmation for me that I'm on the right track. I'll try to get a patch for the functionallity I need together soon, and will submit it here. Thanks, Rob. -- Robert Norris GPG: 1024D/FC18E6C2 Email+Jabber: [EMAIL PROTECTED]Web: http://cataclysm.cx/ signature.asc Description: Digital signature