haiku-website/static/legacy-docs/benewsletter/Issue2-47.html

951 lines
59 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Be Newsletters - Volume 2: 1997</title><link rel="stylesheet" href="be_newsletter.css" type="text/css" media="all" /><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="./images/favicon.ico" /><!--[if IE]>
<link rel="stylesheet" type="text/css" href="be_newsletter_ie.css" />
<![endif]--><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><link rel="start" href="index.html" title="Be Newsletters" /><link rel="up" href="volume2.html" title="Volume 2: 1997" /><link rel="prev" href="Issue2-46.html" title="Issue 2-46, November 19, 1997" /><link rel="next" href="Issue2-48.html" title="Issue 2-48, December 3, 1997" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="Issue2-46.html" title="Issue 2-46, November 19, 1997"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="volume2.html" title="Volume 2: 1997"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="Issue2-48.html" title="Issue 2-48, December 3, 1997"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="headerTR"><div id="navigpeople"><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div><div class="navigboxed" id="naviglang" title="English">en</div></div><div id="headerTC">Be Newsletters - Volume 2: 1997</div></div><div id="headerB">Prev: <a href="Issue2-46.html">Issue 2-46, November 19, 1997</a>  Up: <a href="volume2.html">Volume 2: 1997</a>  Next: <a href="Issue2-48.html">Issue 2-48, December 3, 1997</a></div><hr /></div><div class="article"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Issue2-47"></a>Issue 2-47, November 26, 1997</h2></div></div></div><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Engineering2-47"></a>Be Engineering Insights: Buried Treasures...</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Dominic</span> <span class="surname">Giampaolo</span></span></div></div></div><p>
In a system like the BeOS, much effort goes into documenting the
specifics of programming the BeOS and not as much is spent documenting
more common parts of the libraries, such as the C library.
</p><p>
This makes sense, since there are numerous books on the C library and
POSIX that cover it in adequate detail. Unfortunately, when some of us
incorrigible C weenies add functions or extensions to the C library it
means that they tend not to get documented.
</p><p>
Thus, it pays to peruse the header files found in:
</p><p>
<code class="filename">/boot/develop/headers/posix/</code>
</p><p>
If you poke around in this directory, one "interesting" header you'll
find is <code class="filename">parsedate.h</code>.
This is the header file for the <code class="function">parsedate()</code> function
that I added to the BeOS C library (which is part of
<code class="filename">libroot.so</code>). The
<code class="function">parsedate()</code> routine is a sophisticated date parsing function that knows
how to convert from a human-readable string into a standard <span class="type">time_t</span>
variable (i.e., the number of seconds since January 1, 1970). It even
knows about time zones.
</p><p>
The <code class="function">parsedate()</code> routine is pretty nifty, because it understands common
time formats like "Mon, June 10th, 1993 10:00:03 am GMT". In fact,
<code class="function">parsedate()</code> understands virtually every imaginable verbose time format.
This includes all the typical formats that you'd see in an e-mail message
or Usenet news posting, or that other programs would print using <code class="function">ctime()</code>
or <code class="function">strftime()</code>. The initial list of date formats supported by <code class="function">parsedate()</code>
was generated by culling the Date: line from around 80,000 news postings,
so it's reliably comprehensive.
</p><p>
Having a routine that can parse such strings and return a canonical
integer time is very useful if you ever have to parse an e-mail header or
input a date that was output from another program. One drawback to using
time formats such as these is that their rigidity makes them difficult
for users to type. This becomes an issue if you need users to input a
date as part of your program and you want to use <code class="function">parsedate()</code>.
</p><p>
To remedy the problem of inflexible time formats, <code class="function">parsedate()</code> also
understands many natural date and time specifications. The
<code class="filename">parsedate.h</code>
file alludes to this, but doesn't really go into detail about what these
formats are. The parsedate function accepts the following "natural" time
formats (square brackets indicate an optional item):
</p><pre class="screen">
yesterday
today
tomorrow
[last | next] dayname (monday, tuesday, etc;
e.g., last monday)
[last | next] hour
[last | next] week
[last | next] month
[last | next] year
number minute (e.g. 15 min, -30 minutes)
number hour (e.g. 4 hours, -1 hour)
number day (e.g. 5 days, -3 days)
number month (e.g. 1 month, -2 months)
number year (e.g. 2 years, -3 years)
</pre><p>
Some slightly less casual but still fairly loose formats also work:
</p><pre class="screen">
11/10/97 3pm
Dec 25th 5:00pm
Friday July 9th
10am Sunday
</pre><p>
Because <code class="function">parsedate()</code> understands these types of formats, you can use it in
a variety of situations. It's easy to imagine a reminder/calendar program
that, as an option, lets users just type a day (i.e., remind me next
Thursday of ...). It's also possible to imagine a mail filter which would
scan message text for date strings and build a calendar automatically
(strings like "this Friday" are easily detectable).
</p><p>
<code class="function">parsedate()</code> is also helpful in the BeOS Find panel. For example, if you
need to find everything created in the last two days, you can do a find
by last modification time and simply enter the string "-2 days". Other
common finds might be everything modified since "yesterday" or "last
week".
</p><p>
Another aspect of <code class="function">parsedate()</code> is that when there's a choice of how to
interpret a date, it assumes you want a date after the current time. For
example, if today is Wednesday and you give a time of "monday",
<code class="function">parsedate()</code> interprets that to mean next Monday. If that's not what you
want, you may have to be more explicit or use a relative time format like
"-2 days".
</p><p>
We'll add support for other "casual" date formats as we come across them
(I've added about 10 more since I started writing this article). If you
have suggestions for other common formats, send them to us and we'll see
about adding them to the list (barring ambiguity problems).
</p><p>
To wrap things up, here is simple demonstration program that shows you
how to use <code class="function">parsedate()</code> and lets you play with inputs to it.
</p><pre class="programlisting cpp">
<span class="comment">/*
This is a simple program to demonstrate using parsedate()
on the BeOS.
dbg@be.com
*/</span>
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;
#include &lt;parsedate.h&gt;
<span class="type">int</span>
<code class="function">main</code>(<span class="type">int</span> <code class="parameter">argc</code>, <span class="type">char **</span><code class="parameter">argv</code>)
{
<span class="type">char</span> <code class="varname">str</code>[256];
<span class="type">time_t</span> <code class="varname">remind_time</code>;
<span class="type">struct tm *</span><code class="varname">tm</code>;
<code class="function">printf</code>("\nI am Chronos, the keeper of time.\n");
<code class="function">printf</code>("I am feared by ctime() implementors everywhere.\n");
<code class="function">printf</code>("Enter a time and I will parse it!\n\n");
while (<code class="function">fgets</code>(<code class="varname">str</code>, <code class="function">sizeof</code>(<code class="varname">str</code>), <code class="varname">stdin</code>) != <code class="constant">NULL</code>) {
if (<code class="varname">str</code>[0] == '\n')
continue;
if (<code class="function">strcmp</code>(<code class="varname">str</code>, "quit\n") == 0 ||
<code class="function">strcmp</code>(<code class="varname">str</code>, "exit\n") == 0)
break;
<span class="comment">/*
woo-hoo! here it is...dun dun da nah...
the call to parsedate()!
pretty complex eh? The -1 argument means to parse
relative to now.
*/</span>
<code class="varname">remind_time</code> = <code class="function">parsedate</code>(<code class="varname">str</code>, -1);
if (<code class="varname">remind_time</code> == ~0) {
<code class="function">fprintf</code>(<code class="varname">stderr</code>,
"\nHmmm:\n %sis not recognized.\n", str);
<code class="function">fprintf</code>(<code class="varname">stderr</code>,
"You should tell my trusty assistant dbg@be.com\n\n");
continue;
}
<code class="function">printf</code>("\nThe canonical form for the time you entered was:\n");
<span class="comment">/*
convert to a struct tm which has all the time fields
broken out
*/</span>
<code class="varname">tm</code> = <code class="function">localtime</code>(&amp;<code class="varname">remind_time</code>);
<code class="function">printf</code>(" Year: %d Month: %d Day: %d Hour: %.2d:%.2d\n",
<code class="varname">tm</code>-&gt;<code class="varname">tm_year</code>, <code class="varname">tm</code>-&gt;<code class="varname">tm_mon</code>+1, <code class="varname">tm</code>-&gt;<code class="varname">tm_mday</code>, <code class="varname">tm</code>-&gt;<code class="varname">tm_hour</code>,
<code class="varname">tm</code>-&gt;<code class="varname">tm_min</code>);
<span class="comment">/*
also print the result of ctime()
*/</span>
<code class="function">printf</code>(" %s\n", <code class="function">ctime</code>(&amp;<code class="varname">remind_time</code>));
}
}
</pre><p>
Have fun and maybe next time we'll poke around in that mysterious looking
header file called <code class="filename">malloc_internal.h</code>...
</p></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Engineering2-47-2"></a>A Remembrance of Things Past: Writing Mass Storage Device Drivers</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Dmitriy</span> <span class="surname">Budko</span></span></div></div></div><p>
When was the last time you used a RAM drive? Do you still remember what a
RAM drive is?
</p><p>
On my first PC (an AT 286, 12 MHz, 2 MB RAM) a RAM disk was the only
workable way to use more than 1 MB of memory while running under MS-DOS.
Unlike creaky MS-DOS, a current OS like the BeOS usually uses free memory
in the file system cache; in general, caching algorithms provide much
better performance than a simple RAM disk. Recently though, I was
overcome by inexplicable nostalgia for the good old days and I decided to
write a driver for that "disk" of yesteryear.
</p><p>
So if you have memory to burn, you may want to try using some of your
surplus as a RAM "disk." If nothing else you'll find out that a RAM disk
driver is an excellent example of using a device driver not only as a
hardware interface but also to emulate it! And if you develop a file
system driver, a big RAM disk can speed up the testing.
</p><p>
I assume that you know the basics of BeOS device drivers, so I'll focus
on features specific to mass storage devices (floppy drive, IDE disk,
IEEE 1394 [FireWire] disk) and on some tricks related to the volatile
nature of RAM.
</p><p>
The driver has to support all standard entry points. In addition it has
to handle some mass storage device I/O control codes.
</p><p>
I tried to make the driver as simple as possible, so it supports only one
RAM disk. Its dynamic configuration is almost nonexistent, and its
emulation of the hard drive seek process is very primitive. This
simplification let me forget about synchronization problems.
</p><p>
Here's the driver source code. You can find the original source,
unaltered for or by e-mail transmission, at:
</p><p>
ftp://ftp.be.com/pub/samples/preview/drivers/ramdrive.zip
</p><pre class="programlisting c">
<span class="comment">/****************** cut here ******************************/</span>
#include &lt;OS.h&gt;
#include &lt;Drivers.h&gt;
#include &lt;KernelExport.h&gt;
#include &lt;stdlib.h&gt;
<span class="type">status_t</span> <code class="function">vd_open</code>(<span class="type">const char *</span><code class="parameter">name</code>, <span class="type">uint32</span> <code class="parameter">flags</code>,
<span class="type">void **</span><code class="parameter">cookie</code>);
<span class="type">status_t</span> <code class="function">vd_free</code> (<span class="type">void *</span><code class="parameter">cookie</code>);
<span class="type">status_t</span> <code class="function">vd_close</code>(<span class="type">void *</span><code class="parameter">cookie</code>);
<span class="type">status_t</span> <code class="function">vd_control</code>(<span class="type">void *</span><code class="parameter">cookie</code>, <span class="type">uint32</span> <code class="parameter">msg</code>, <span class="type">void *</span><code class="parameter">buf</code>,
<span class="type">size_t</span> <code class="parameter">size</code>);
<span class="type">status_t</span> <code class="function">vd_read</code>(<span class="type">void *</span><code class="parameter">cookie</code>, <span class="type">off_t</span> <code class="parameter">pos</code>, <span class="type">void *</span><code class="parameter">buf</code>,
<span class="type">size_t *</span><code class="parameter">count</code>);
<span class="type">status_t</span> <code class="function">vd_write</code>(<span class="type">void *</span><code class="parameter">cookie</code>, <span class="type">off_t</span> <code class="parameter">pos</code>, <span class="type">constvoid *</span><code class="parameter">buf</code>,
<span class="type">size_t *</span><code class="parameter">count</code>);
static <span class="type">void</span> <code class="function">format_ram_drive</code>(<span class="type">void*</span> <code class="parameter">buf</code>);
static <span class="type">uchar*</span> <code class="function">create_ram_drive_area</code>(<span class="type">size_t</span> <code class="parameter">drive_size</code>);
static <span class="type">status_t</span> <code class="function">delete_ram_drive_area</code>(<span class="type">void</span>);
static <span class="type">void</span> <code class="function">emulate_seek</code>(<span class="type">off_t</span> <code class="parameter">pos</code>);
#define <code class="constant">RAM_DRIVE_RELEASE_MEMORY</code> (<code class="constant">B_DEVICE_OP_CODES_END</code>+1)
#define <code class="constant">RAM_DRIVE_EMULATE_SEEK</code> (<code class="constant">B_DEVICE_OP_CODES_END</code>+2)
#define <code class="constant">RAM_DRIVE_SIZE</code> (8*1024*1024)
#define <code class="constant">RAM_BLOCK_SIZE</code> 512
#define <code class="constant">MAX_SEEK_TIME</code> 1000.0 <span class="comment">/* microseconds */</span>
#define <code class="constant">PREFETCH_BUFFER_SIZE</code> (32*1024)
static <span class="type">const char*</span> const
<code class="varname">ram_drive_area_name</code> = "RAM drive area";
<span class="type">uchar</span> <code class="varname">icon_disk</code>[<code class="constant">B_LARGE_ICON</code> * <code class="constant">B_LARGE_ICON</code>];
<span class="type">uchar</span> <code class="varname">icon_disk_mini</code>[<code class="constant">B_MINI_ICON</code> * <code class="constant">B_MINI_ICON</code>];
<span class="type">int</span> <code class="varname">emulate_seek_flag</code> = <code class="constant">FALSE</code>;
<span class="type">uchar *</span> <code class="varname">ram</code> = <code class="constant">NULL</code>;
static <span class="type">const char *</span><code class="varname">vd_name</code>[] = {
"disk/virtual/ram_drive",
NULL
};
<span class="type">device_hooks</span> <code class="varname">vd_devices</code> = {
vd_open,
vd_close,
vd_free,
vd_control,
vd_read,
vd_write
};
<span class="type">status_t</span>
<code class="function">init_driver</code>(<span class="type">void</span>)
{
<code class="function">dprintf</code>("vd driver: %s %s, init_driver()\n",
__DATE__, __TIME__);
<code class="varname">ram</code> = <code class="function">create_ram_drive_area</code>(<code class="constant">RAM_DRIVE_SIZE</code>);
if(<code class="varname">ram</code> == <code class="constant">NULL</code>)
return <code class="constant">B_ERROR</code>;
return <code class="constant">B_NO_ERROR</code>;
}
<span class="type">void</span>
<code class="function">uninit_driver</code>(<span class="type">void</span>)
{
<code class="function">dprintf</code>("vd driver: uninit_driver()\n");
}
<span class="type">const char**</span>
<code class="function">publish_devices</code>()
{
<code class="function">dprintf</code>("vd driver: publish_devices()\n");
return <code class="varname">vd_name</code>;
}
<span class="type">device_hooks*</span>
<code class="function">find_device</code>(<span class="type">const char*</span> <code class="parameter">name</code>)
{
<code class="function">dprintf</code>("vd driver: find_device()\n");
return &amp;<code class="varname">vd_devices</code>;
}
<span class="type">status_t</span>
<code class="function">vd_open</code>(<span class="type">const char *</span><code class="parameter">dname</code>, <span class="type">uint32</span> <code class="parameter">flags</code>, <span class="type">void **</span><code class="parameter">cookie</code>)
{
<code class="function">dprintf</code>("vd driver: open(%s)\n", <code class="parameter">dname</code>);
return <code class="constant">B_NO_ERROR</code>;
}
<span class="type">status_t</span>
<code class="function">vd_free</code>(<span class="type">void *</span><code class="parameter">cookie</code>)
{
<code class="function">dprintf</code>("vd driver: free()\n");
return <code class="constant">B_NO_ERROR</code>;
}
<span class="type">status_t</span>
<code class="function">vd_close</code>(<span class="type">void *</span><code class="parameter">cookie</code>)
{
<code class="function">dprintf</code>("vd driver: close()\n");
return <code class="constant">B_NO_ERROR</code>;
}
<span class="type">status_t</span>
<code class="function">vd_read</code>(<span class="type">void *</span><code class="parameter">cookie</code>, <span class="type">off_t</span> <code class="parameter">pos</code>, <span class="type">void *</span><code class="parameter">buf</code>, <span class="type">size_t *</span><code class="parameter">count</code>)
{
<span class="type">size_t</span> <code class="varname">len</code>;
<span class="type">status_t</span> <code class="varname">ret</code> = <code class="constant">B_NO_ERROR</code>;
if(<code class="parameter">pos</code> &gt;= <code class="constant">RAM_DRIVE_SIZE</code>)
{
<code class="varname">len</code> = 0;
}
else
{
<code class="varname">len</code> = (<code class="parameter">pos</code> + (*<code class="parameter">count</code>) &gt; <code class="constant">RAM_DRIVE_SIZE</code>) ?
(<code class="constant">RAM_DRIVE_SIZE</code> - <code class="parameter">pos</code>) : (*<code class="parameter">count</code>);
<code class="function">emulate_seek</code>(<code class="parameter">pos</code>);
<code class="function">memcpy</code>(<code class="parameter">buf</code>, <code class="varname">ram</code>+<code class="parameter">pos</code>, <code class="varname">len</code>);
}
*<code class="parameter">count</code> = <code class="varname">len</code>;
return <code class="varname">ret</code>;
}
<span class="type">status_t</span>
<code class="function">vd_write</code>(<span class="type">void *</span><code class="parameter">cookie</code>, <span class="type">off_t</span> <code class="parameter">pos</code>, <span class="type">constvoid *</span><code class="parameter">buf</code>,
<span class="type">size_t *</span><code class="parameter">count</code>)
{
<span class="type">size_t</span> <code class="varname">len</code>;
<span class="type">status_t</span> <code class="varname">ret</code> = <code class="constant">B_NO_ERROR</code>;
if(<code class="parameter">pos</code> &gt;= <code class="constant">RAM_DRIVE_SIZE</code>)
{
<code class="varname">len</code> = 0;
}
else
{
<code class="varname">len</code> = (<code class="parameter">pos</code> + (*<code class="parameter">count</code>) &gt; <code class="constant">RAM_DRIVE_SIZE</code>) ?
(<code class="constant">RAM_DRIVE_SIZE</code> - <code class="parameter">pos</code>) : (*<code class="parameter">count</code>);
<code class="function">emulate_seek</code>(<code class="parameter">pos</code>);
<code class="function">memcpy</code>(<code class="varname">ram</code>+<code class="parameter">pos</code>, <code class="parameter">buf</code>, <code class="varname">len</code>);
}
*<code class="parameter">count</code> = <code class="varname">len</code>;
return <code class="varname">ret</code>;
}
<span class="type">status_t</span>
<code class="function">vd_control</code>(<span class="type">void *</span><code class="parameter">cookie</code>, <span class="type">uint32</span> <code class="parameter">ioctl</code>, <span class="type">void *</span><code class="parameter">arg1</code>,
<span class="type">size_t</span> <code class="parameter">len</code>)
{
<span class="type">device_geometry *</span><code class="varname">dinfo</code>;
dprintf("vd driver: control(%d)\n", <code class="parameter">ioctl</code>);
switch (<code class="parameter">ioctl</code>)
{
<span class="comment">/* generic mass storage device IO control codes */</span>
case <code class="constant">B_GET_GEOMETRY</code>:
<code class="varname">dinfo</code> = (<span class="type">device_geometry *</span>) <code class="parameter">arg1</code>;
<code class="varname">dinfo</code>-&gt;<code class="varname">sectors_per_track</code> =
<code class="constant">RAM_DRIVE_SIZE</code>/<code class="constant">RAM_BLOCK_SIZE</code>;
<code class="varname">dinfo</code>-&gt;<code class="varname">cylinder_count</code> = 1;
<code class="varname">dinfo</code>-&gt;<code class="varname">head_count</code> = 1;
<code class="varname">dinfo</code>-&gt;<code class="varname">bytes_per_sector</code> = <code class="constant">RAM_BLOCK_SIZE</code>;
<code class="varname">dinfo</code>-&gt;<code class="varname">removable</code> = <code class="constant">FALSE</code> ;
<code class="varname">dinfo</code>-&gt;<code class="varname">read_only</code> = <code class="constant">FALSE</code>;
<code class="varname">dinfo</code>-&gt;<code class="varname">device_type</code> = <code class="constant">B_DISK</code>;
<code class="varname">dinfo</code>-&gt;<code class="varname">write_once</code> = <code class="constant">FALSE</code>;
return <code class="constant">B_NO_ERROR</code>;
case <code class="constant">B_FORMAT_DEVICE</code>:
<code class="function">format_ram_drive</code>(<code class="varname">ram</code>);
return <code class="constant">B_NO_ERROR</code>;
case <code class="constant">B_GET_DEVICE_SIZE</code>:
*(<span class="type">size_t*</span>)<code class="parameter">arg1</code> = <code class="constant">RAM_DRIVE_SIZE</code>;
return <code class="constant">B_NO_ERROR</code>;
case <code class="constant">B_GET_ICON</code>:
switch (((<span class="type">device_icon *</span>)<code class="parameter">arg1</code>)-&gt;<code class="varname">icon_size</code>)
{
case <code class="constant">B_LARGE_ICON</code>:
<code class="function">memcpy</code>(((<span class="type">device_icon *</span>)<code class="parameter">arg1</code>)-&gt;<code class="varname">icon_data</code>, <code class="varname">icon_disk</code>,
<code class="constant">B_LARGE_ICON</code> * <code class="constant">B_LARGE_ICON</code>);
break;
case <code class="constant">B_MINI_ICON</code>:
<code class="function">memcpy</code>(((<span class="type">device_icon *</span>)<code class="parameter">arg1</code>)-&gt;<code class="varname">icon_data</code>,
<code class="varname">icon_disk_mini</code>, <code class="constant">B_MINI_ICON</code> * <code class="constant">B_MINI_ICON</code>);
break;
default:
return <code class="constant">B_BAD_TYPE</code>;
}
return <code class="constant">B_NO_ERROR</code>;
<span class="comment">/* device specific IO control codes */</span>
case <code class="constant">RAM_DRIVE_RELEASE_MEMORY</code>:
return <code class="function">delete_ram_drive_area</code>();
case <code class="constant">RAM_DRIVE_EMULATE_SEEK</code>:
<code class="varname">emulate_seek_flag</code> = *(<span class="type">int*</span>)<code class="parameter">arg1</code>;
return <code class="constant">B_NO_ERROR</code>;
default:
return <code class="constant">B_ERROR</code>;
}
}
static <span class="type">void</span> <code class="function">format_ram_drive</code>(<span class="type">void*</span> <code class="parameter">buf</code>)
{
static <span class="type">const char</span> <code class="varname">format_str</code>[16] = "RAM drive ";
<span class="type">uchar*</span> <code class="varname">ptr</code> = (<span class="type">uchar*</span>)<code class="parameter">buf</code>;
<span class="type">off_t</span> <code class="varname">i</code>;
<code class="function">dprintf</code>("vd driver: format_ram_drive(%08x)\n", <code class="parameter">buf</code>);
for(<code class="varname">i</code>=0; <code class="varname">i</code>&lt;<code class="constant">RAM_DRIVE_SIZE</code>/16; <code class="varname">i</code>++)
{
<code class="function">memcpy</code>(<code class="varname">ptr</code>, <code class="varname">format_str</code>, 16);
<code class="varname">ptr</code> += 16;
}
}
static <span class="type">uchar*</span>
<code class="function">create_ram_drive_area</code>(<span class="type">size_t</span> <code class="parameter">drive_size</code>)
{
<span class="type">void*</span> <code class="varname">addr</code>;
<span class="type">area_id</span> <code class="varname">area</code> = find_area(<code class="varname">ram_drive_area_name</code>);
if(<code class="varname">area</code> == <code class="constant">B_NAME_NOT_FOUND</code>)
{
<code class="varname">area</code> = <code class="function">create_area</code>(<code class="varname">ram_drive_area_name</code>,
&amp;<code class="varname">addr</code>,
<code class="constant">B_ANY_KERNEL_ADDRESS</code>,<span class="comment">/*kernel team will own this area*/</span>
<code class="parameter">drive_size</code>,
<code class="constant">B_LAZY_LOCK</code>,
<code class="constant">B_READ_AREA</code> | <code class="constant">B_WRITE_AREA</code>);
if((<code class="varname">area</code>==<code class="constant">B_ERROR</code>) ||
(<code class="varname">area</code>==<code class="constant">B_NO_MEMORY</code>) ||
(<code class="varname">area</code>==<code class="constant">B_BAD_VALUE</code>))
<code class="varname">addr</code> = <code class="constant">NULL</code>;
}
else
{
<span class="type">area_info</span> <code class="varname">info</code>;
<code class="function">get_area_info</code>(<code class="varname">area</code>, &amp;<code class="varname">info</code>);
<code class="varname">addr</code> = <code class="varname">info</code>.<code class="varname">address</code>;
}
return (<span class="type">uchar*</span>)<code class="varname">addr</code>;
}
static <span class="type">status_t</span>
<code class="function">delete_ram_drive_area</code>(<span class="type">void</span>)
{
<span class="type">area_id</span> <code class="varname">area</code> = <code class="function">find_area</code>(<code class="varname">ram_drive_area_name</code>);
if(<code class="varname">area</code> == <code class="constant">B_NAME_NOT_FOUND</code>)
return <code class="constant">B_ERROR</code>;
else
return <code class="function">delete_area</code>(<code class="varname">area</code>);
}
static <span class="type">void</span>
<code class="function">emulate_seek</code>(<span class="type">off_t</span> <code class="parameter">pos</code>)
{
static <span class="type">off_t</span> <code class="varname">old_pos</code> = 0;
if(!<code class="varname">emulate_seek_flag</code>)
return;
if(abs(<code class="parameter">pos</code>-<code class="varname">old_pos</code>)&gt;<code class="constant">PREFETCH_BUFFER_SIZE</code>)
{
<code class="varname">old_pos</code> = <code class="parameter">pos</code>;
<code class="function">snooze</code>((<span class="type">int</span>)(<code class="function">rand()</code>* <code class="constant">MAX_SEEK_TIME</code>)/<code class="constant">RAND_MAX</code>);
}
}
<span class="comment">/****************** cut here ******************************/</span>
</pre><p>
What happens is that <code class="function">init_driver()</code> creates the kernel memory area that's
used to store the data. The driver can't use
<code class="function">malloc()</code>/<code class="function">free()</code> because when
the driver is unloaded the memory (and all data) is lost. It's actually
present somewhere, but there's no easy way to find it when the driver is
loaded again.
</p><p>
So <code class="function">init_driver()</code> calls <code class="function">create_ram_drive_area()</code>, which tries to find the
previously created memory area with the name "RAM drive area." If the
search is unsuccessful the driver is loaded the first time. In that case
<code class="function">create_ram_drive_area()</code> creates the memory area. It uses a currently
undocumented flag, <code class="constant">B_ANY_KERNEL_ADDRESS</code>. This flag gives ownership of
this memory area to the kernel, so the area will not be deleted when the
application that opened the driver quits.
</p><p>
It also uses the <code class="constant">B_LAZY_LOCK</code> flag so the driver doesn't consume RAM until
the first time you use it. I could have used <code class="constant">B_FULL_LOCK</code> and put the
memory allocation in <code class="function">vd_open()</code>, but being lazy I didn't want to provide a
critical section synchronization for it.
</p><p>
<code class="function">vd_open()</code> can be called a few times simultaneously;
<code class="function">init_driver()</code> cannot.
<code class="function">publish_devices()</code> creates the device file in
<code class="filename">/dev/disk/virtual/ram_drive</code>.
The <code class="filename">/virtual/ram_drive</code> part of the name is arbitrary, but
<code class="filename">/dev/disk</code>
is mandatory if you want to use a standard disk setup program—like
<span class="application">DriveSetup</span>—to configure the RAM disk.
</p><p>
<code class="function">vd_open()</code>, <code class="function">vd_free()</code>, and
<code class="function">vd_close()</code> do nothing and return success.
</p><p>
<code class="function">vd_read()</code> and <code class="function">vd_write()</code> check
to see if the caller tries to read/write
over the end of the disk. They adjust the requested length accordingly,
then simply copy the data from/to the requested offset in the RAM area
to/from the caller's buffer.
</p><p>
If <code class="varname">emulate_seek_flag</code> is set the driver calls
<code class="function">emulate_seek()</code>.
<code class="function">emulate_seek()</code> is a crude imitation of real hard drive mechanics and
caching. The current implementation is not in a critical section so it is
capable of multiple concurrent seeks. It would be great to have a real
drive with an infinite number of head arms! Readers are welcome to create
a more realistic model.
</p><p>
Still, with this function implemented, the RAM drive is better suited for
testing a file system driver. It can block the caller's thread as a driver
for a real drive would do.
</p><p>
<code class="function">vd_control()</code> handles four generic I/O control codes for a mass storage
device: <code class="constant">B_GET_GEOMETRY</code>, <code class="constant">B_FORMAT_DEVICE</code>,
<code class="constant">B_GET_DEVICE_SIZE</code>, <code class="constant">B_GET_ICON</code>.
The first three are mandatory; the last one is optional.
</p><p>
This driver has zero-initialized arrays for large and small icons. The
real driver should provide more pleasing icons than black rectangles.
</p><p>
<code class="constant">RAM_DRIVE_RELEASE_MEMORY</code> deletes the allocated memory area and thus
destroys all information on the RAM drive. <code class="constant">RAM_DRIVE_EMULATE_SEEK</code> sets or
clears the <code class="varname">emulate_seek_flag</code>. A control panel application for the RAM
drive could send such commands.
</p><p>
Now here's how to build and install the driver:
</p><div class="orderedlist"><ol><li><p>
Instruct the linker to produce an add-on image.
</p></li><li><p>
Disable linking to the default shared system libraries.
</p></li><li><p>
Export the driver's entry points—for example, by exporting
everything.
</p></li><li><p>
Place a copy of the appropriate kernel file (<code class="filename">kernel_joe</code>,
<code class="filename">kernel_mac</code>, or <code class="filename">kernel_intel</code>) in your project directory. Link against
this file.
</p></li><li><p>
Copy the compiled driver in the
<code class="filename">/boot/home/config/add-ons/kernel/drivers</code> directory.
</p></li><li><p>
Use your favorite disk format program or BeOS
preferences/DriveSetup to partition and/or install BFS on the
<code class="filename">/dev/disk/virtual/ram_drive</code> device.
</p></li></ol></div><p>
That's it. You're all set!
</p><p>
I hope that this simple device driver may help get somebody started in
BeOS driver development. If any seasoned device drivers out there have
feature requests or comments (why does Be have such-and-such stupid
restriction or does not have such-and-such device driver API ...), let me
know and I'll try to implement them. The Intel port in particular may
require same changes: @#$% ISA 16 MB limit on DMA, PCI interrupt sharing,
ISA PnP, etc.
</p><p>
Speak now and you can make your life running the BeOS on Intel that much
easier!
</p></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="DevWorkshop2-47"></a>Developers' Workshop: BYOB!</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Doug</span> <span class="surname">Wright</span></span></div></div></div><p>
"Developers' Workshop" is a new weekly feature that provides answers to
our developers' questions. Each week, a Be technical support or
documentation professional will choose a question (or two) sent in by an
actual developer and provide an answer.
</p><p>
We've created a new section on our website. Please send us your
Newsletter topic suggestions by visiting the website at:
http://www.be.com/developers/suggestion_box.html.
</p><p>
Hello Be people. As the newest Developer Technical Support Engineer, I
have spoken with some of you recently regarding specific problems but
this is my first taste of the Be Newsletter audience. Playing live shows
in a band once or twice a month has tamed my wild urge to run and hide in
front of a crowd, but writing an article that persists over time
definitely feels different then being live on stage.
</p><p>
So with a little nervousness, I present you with my first (not last!) bit
of Be insight, in two parts. The subjects were inspired by many things
but the titles were inspired by my favorite thing—BYOB!
</p><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id605525"></a>Part I: Bring Your Own Bugs!</h3></div></div></div><p>
Melissa has graciously given me the task of evaluating bugs submitted by
developers. In attempting to climb this ant hill I have found that some
people are natural bug writers and others, well, are more like Hostess
Twinkies. To help out all those American snack cakes out there, I will
offer a few guidelines to writing a good bug (and the only *good* bugs
are the ones you can hunt down and kill!).
</p><p>
Step 1: A reproducible case is needed. If you can't reproduce it, neither
can we.
</p><p>
Step 2: Document each step necessary to reproduce the bug. For example:
</p><div class="orderedlist"><ol><li><p>
Open a Terminal
</p></li><li><p>
Type twinky -old
</p></li><li><p>
Open a Tracker window
</p></li><li><p>
Create a folder called Hostess
</p></li><li><p>
Right click the folder
</p></li><li><p>
Crash!
</p></li></ol></div><p>
Step 3: Document your machine configuration. Include all the hardware AND
software your are running. For example, a developer recently forgot to
mention that <code class="code">MALLOC_DEBUG</code> was turned on.
</p><p>
Step 4: If the app that crashes is yours, include the code. Don't worry,
that little window on the bug report form scrolls for a long time! Just
paste it right in there.
</p><p>
Now I know you're thinking "Hey, I've got 50 source files, they won't all
fit." You need to find the piece of code that is causing the crash and
put it in a little test app.
</p><p>
HelloWorld is great for this. It has an app and a window and a view. Most
bugs don't need more than that to cause trouble. HINT: This can also help
you find bugs in your own code!
</p><p>
If the only way to cause the crash is to include your entire source, then
zip it up and send it in to devservices@be.com with a reference to the
bug number that you get when you submit the description using the web
form.
</p><p>
Step 5: The last part of Step 4 is really Step 5. Write down your bug
number so that you can contact us about it in the future.
</p><p>
If you skip any one of these steps, your bug will more than likely get
classified as "Unreproducible." This is bad for you and for Be, because
your bug will still be running around in the next release causing you and
everyone else problems! If you have any trouble with the bug reporting
process or you feel that we've made a grave error and classified your bug
as a feature, please don't hesitate to fill out a Developer tech Support
form in the Registered Developer Area and we will look into your problem.
</p></div><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id605634"></a>Part II: Build Your Own Buttons!</h3></div></div></div><p>
Are you building that killer tractor app, and you want the interface to
be oh-so-cool? It's not going to knock their socks of with a bunch of
plain-jane buttons. You need to customize! So I've prepared some sample
code to get you started making your very own buttons. Find the complete
archive on the Be website at:
</p><p>
ftp://ftp.be.com/pub/samples/preview/intro/ButtonWorld.zip
</p><p>
The <code class="classname">BPictureButton</code> class is a button that
takes two <code class="classname">BPicture</code>s as
arguments. You can build these pictures out of <code class="classname">BBitmap</code>s, a combination of
<code class="classname">BBitmap</code>s and <code class="classname">BButton</code>s
(for that grey look) or any other drawing routine.
The two pictures each represent one of two states, on and off.
</p><p>
I started by scanning a familiar form. I used Photoshop on the Mac ;-( to
save my scanned image in raw format. You need to remember the dimensions
of the image and the bit depth. The width needs to be a multiple of four
in order to use the command line tool craw to convert them into code. My
images were 48 x 48 so I just typed "$craw 48 48 myrawimage" in a
terminal.
</p><p>
(For more information on how to use craw check out...
</p><p>
<a class="xref" href="Issue1-15.html#Engineering1-15" title="Be Engineering Insights: craw, shex, and script: Excuse Me?">Be Engineering Insights: craw, shex, and script: Excuse Me?</a>
</p><p>
This is an oldie but a goodie! William Adams also addressed creating
custom graphics from images in a <a class="xref" href="Issue2-23.html#News2-23" title="News From The Front">News From The Front</a> article...
</p><p>
Some of the samples he referred to have been moved, including mkimghdr,
which is now at...
</p><p>
ftp://ftp.be.com/pub/samples/preview/interface_kit/mkimghdr.tgz.)
</p><p>
Craw generates an unsigned char array. blue4x4 and blue4x4on are the
names of my two arrays. Now I'm ready to fill some bitmaps and create a
button...
</p><pre class="programlisting cpp">
<span class="comment">/* NOTE: This is all happening during the construction of a
Window inheriting from a BWindow. */</span>
<code class="classname">BRect</code> <code class="varname">rect</code>;
<code class="varname">rect</code>.<code class="methodname">Set</code>(0,0,47,47);
<span class="comment">//bitmaps for the pictures</span>
<code class="classname">BBitmap</code> <code class="varname">onBitmap</code>(<code class="varname">rect</code>, <code class="constant">B_COLOR_8_BIT</code> );
<code class="classname">BBitmap</code> <code class="varname">offBitmap</code>(<code class="varname">rect</code>, <code class="constant">B_COLOR_8_BIT</code> );
<span class="comment">//fill bitmap</span>
<code class="varname">onBitmap</code>.<code class="methodname">SetBits</code>(<code class="varname">blue4x4on</code>, 18432, 0, <code class="constant">B_COLOR_8_BIT</code>);
<code class="varname">offBitmap</code>.<code class="methodname">SetBits</code>(<code class="varname">blue4x4</code>, 18432, 0, <code class="constant">B_COLOR_8_BIT</code>);
<span class="comment">/* Next, I create two BPictures and draw my bitmaps
in them. */</span>
<span class="comment">//tempview for creating the picture</span>
<span class="type"><code class="classname">BView</code> *</span><code class="varname">tempView</code> =
new <code class="classname">BView</code>(<code class="varname">rect</code>, "temp", <code class="constant">B_FOLLOW_NONE</code>, <code class="constant">B_WILL_DRAW</code>);
<code class="methodname">AddChild</code>(<code class="varname">tempView</code>);
<span class="comment">//create on picture</span>
<span class="type"><code class="classname">BPicture</code> *</span><code class="varname">on</code>;
<code class="varname">tempView</code>-&gt;<code class="methodname">BeginPicture</code>(new <code class="classname">BPicture</code>);
<code class="varname">tempView</code>-&gt;<code class="methodname">DrawBitmap</code>(&amp;<code class="varname">onBitmap</code>);
<code class="varname">on</code> = <code class="varname">tempView</code>-&gt;<code class="methodname">EndPicture</code>();
<span class="comment">//create off picture</span>
<span class="type"><code class="classname">BPicture</code> *</span><code class="varname">off</code>;
<code class="varname">tempView</code>-&gt;<code class="methodname">BeginPicture</code>(new <code class="classname">BPicture</code>);
<code class="varname">tempView</code>-&gt;<code class="methodname">DrawBitmap</code>(&amp;<code class="varname">offBitmap</code>);
<code class="varname">off</code> = <code class="varname">tempView</code>-&gt;<code class="methodname">EndPicture</code>();
<span class="comment">//get rid of tempview</span>
<code class="methodname">RemoveChild</code>(<code class="varname">tempView</code>);
delete <code class="varname">tempView</code>;
<span class="comment">/* Finally I create my BPicture button and the other things
that it needs including the message that will be sent to
its target. */</span>
<span class="comment">//create a message for the button</span>
<span class="type"><code class="classname">BMessage</code> *</span><code class="varname">pictmsg</code> = new <code class="classname">BMessage</code>(<code class="constant">BUTTON_MSG</code>);
<code class="varname">pictmsg</code>-&gt;<code class="methodname">AddString</code>("text", "Picture Button");
<span class="comment">//create a picture button using the two pictures</span>
<code class="varname">rect</code>.<code class="methodname">Set</code>( 120, 45, 167, 92 );
<span class="type"><code class="classname">BPictureButton</code>*</span> <code class="varname">pictureButton</code> =
new <code class="classname">BPictureButton</code>(<code class="varname">rect</code>, "picture", <code class="varname">off</code>, <code class="varname">on</code>, <code class="varname">pictmsg</code>,
<code class="constant">B_TWO_STATE_BUTTON</code>);
<span class="comment">/* The last argument for the BPictureButton is a flag for
the mode. B_TWO_STATE_BUTTON behaves like a toggle
switch. Turn it on with one click. Turn it off with
another. A B_ONE_STATE_BUTTON is only on while you hold
the mouse down. */</span>
<span class="comment">/* Once you have created your button you can add it as a
child to the window. The buttonView is a BTextView to
which we will send our message. */</span>
<span class="comment">// add view and button to window</span>
<code class="methodname">AddChild</code>(<code class="varname">buttonView</code>);
<code class="methodname">AddChild</code>(<code class="varname">pictureButton</code>);
<span class="comment">/* Finally in order to direct the message your button sends
you need to assign it a target. */</span>
<span class="comment">// make the view the target of the buttons</span>
<code class="varname">pictureButton</code>-&gt;<code class="methodname">SetTarget</code>(<code class="varname">buttonView</code>);
</pre><p>
Now when you click on the button, a message is sent to the <code class="varname">buttonView</code>
which displays the string contained by the message. To see how the
<code class="classname">BStringView</code> handles the message, please check out the complete sample.
Have fun and remember, we're happy to have you BYOB at Be! If you need
more information, don't hesitate to ask!
</p></div></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Gassee2-47"></a>A Nice Comdex</h2></div><div xmlns:d="http://docbook.org/ns/docbook"><span xmlns="http://www.w3.org/1999/xhtml" class="author">By <span class="firstname">Jean-Louis</span> <span class="surname">Gassée</span></span></div></div></div><p>
It is fashionable to complain about Comdex, from the bad food, the taxi
lines, expensive hotel rooms, sore feet at the end of the day and silly
carnival acts in the booths of companies who should know better. Perhaps,
but I still like Comdex, and I liked this one even better, for two
reasons.
</p><p>
The first is Umax. Our partner graciously hosted us on their booth in the
main hall, providing us with the opportunity to show both the PowerPC and
the Intel versions of the BeOS as befits their own business addressing
both standards.
</p><p>
As expected we got both good reactions and blank stares, when not eyes
rolling. Some visitors knew us, or had heard about us and were happy to
get a progress report. Others had no idea we existed and a few questioned
our sanity. When we got the opportunity, we disposed easily of the mental
health question by pointing out the difference between OS/2 trying to
dislodge Windows and the BeOS happily coexisting with the general-purpose
OS.
</p><p>
This experience is a useful reminder of what awaits us in the Intel-based
market. It's not just larger than the PowerPC market, it's much different
and our reputation, the exposure we enjoy in the PowerPC segment, aren't
worth much in the new space. The newer Intel version performed well
during the week, much better than we had anticipated and, towards the
end, we sneaked in a "just baked" port on an Intel-powered laptop.
</p><p>
The second reason to like Comdex this year is the abundance of technology
coming out of gestation, ready to become a real product at Fry's some
time in the next twelve months. Flat panels were big, literally and in
their ubiquity. A forty-six-inch panel is still horribly expensive, but
the smaller models are soon to grace the desktops of Corporate America.
</p><p>
Closer to our business, video cameras, ever higher-speed graphic cards,
still cameras, IEEE 1394 connections, high-bandwidth disk adapters...all
sing the song of better, faster, more affordable digital media.
</p><p>
This year we didn't hear the old saw: "The industry is becoming
commoditized, boring, less innovative." Confusing, a little disorganized
perhaps, but we like that, there is little room for a start-up such as
ours in a perfectly stable and organized world.
</p><p>
As for the expensive rooms and the bad food, a minivan gets you a little
out of the way, the hotel prices plummet and you even find restaurants
without slot machines.
</p></div><hr class="pagebreak" /><div class="sect1"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BeDevTalk2-47"></a>BeDevTalk Summary</h2></div></div></div><p>
BeDevTalk is an unmonitored discussion group in which technical
information is shared by Be developers and interested parties. In this
column, we summarize some of the active threads, listed by their subject
lines as they appear, verbatim, in the mail.
</p><p>
To subscribe to BeDevTalk, visit the mailing list page on our web site:
http://www.be.com/aboutbe/mailinglists.html.
</p><div class="sect2"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id606282"></a>NEW</h3></div></div></div><div class="sect3"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id606288"></a>Subject: Help with error...</h4></div></div></div><p>
We've all seen it...the "Data &gt; 32K" compiler error message. What does
it mean? It means you've asked for too much local data. The 32k limit
is enforced by the compiler in order to be ANSI compliant, but beyond
that, is biting off huge chunks of local data bad programming? Earl
Malmrose saw some advantages in the practice:
</p><p>
<span class="quote">Being local, you have automatic garbage collection of a sort - [the
data] will never be leaked. You also have to write less code.</span>
</p><p>
Jon Watte listed some reasons behind the limitation, among which:
</p><p>
<span class="quote">In a multi-threaded environment, each thread has to be given its own
stack...there is a very real trade-off between how many threads you can
create, and how much stack space they get.</span>
</p><p>
Nonetheless, there were objections to the "bad programming practice"
characterization. It was contended that the negative citations were
architecture specific (hardware or software)—that there were no
intrinsic reasons why huge local data is bad. Then Osma Ahvenlampi
added this:
</p><p>
<span class="quote">In addition to the problems pointed out by others, note that it
[relying on the stack for memory allocation] will not give you any kind
of error recovery. What happens when there isn't enough memory to give
you that big a stack frame? Crash, most likely.</span>
</p></div><div class="sect3"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id606350"></a>Subject: Digital Signatures on the BeOS</h4></div></div></div><p>
Can a PGP-style signature be stored as an attribute of a file? (Sure.)
But would the attribute itself affect the signature for the file? (Not
if you didn't want it to—attributes can be selectively ignored.)
</p><p>
Expanding the equation, what if you wanted to verify attributes as well
as data? Peter Folk suggested a 3-tier scheme:
</p><ul class="itemizedlist"><li><p>
PGP__SIG is a signature for the main data stream.
</p></li><li><p>
PGP_&lt;attributename&gt;_SIG is a signature for whichever attributes
you care to sign (excluding PGP__SIG).
</p></li><li><p>
PGPSIG_SIG is a signature of all the PGP_*_SIG attributes.
</p></li></ul><p>
This may be overkill, suggests Jon Watte:
</p><p>
<span class="quote">Having one signature for each attribute is rather wasteful... Instead,
you can sign the data with one signature, and the union of all
non-changing [attributes] with another; that should be enough even for
the most paranoid among us.</span>
</p><p>
Speaking of paranoia, the thread veered into a discussion of reliable
key retrieval and verification. Anthony Towns provided a tidy wish list
that summarized the elements of the problem (paraphrased here):
</p><ul class="itemizedlist"><li><p>
Some way of storing public keys. This would naturally expand to
include encryption as well as verification keys...
</p></li><li><p>
Some way of easily requesting keys. This is strongly related to
the public key database: first you check it, then you check a public
key server somewhere.
</p></li><li><p>
Library support for verifying signatures.
</p></li><li><p>
Convenient methods for signing files (including support for
various signature algorithms).
</p></li><li><p>
An integrated encryption API.
</p></li></ul><p>
But should Be be in the encryption business? Some folks think not.
</p><p>
Also, it was contended that the entire signature-in-an-attribute
approach is flawed: Attributes can get lost in an ftp transfer (for
example). Important signature information should be encoded in the data
portion of a file.
</p></div><div class="sect3"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id606461"></a>Subject: BRect confusion</h4></div></div></div><p>
Should the <code class="methodname">Width()</code> of a <code class="classname">BRect</code>
return the "virtual" width of the
rectangle, or the number of pixels the stroked and filled rect touches?
The function returns the former, a practice that many developers are
confused by; when you ask for the width of a rectangle, you should get
a count of the number of (horizontal) pixels it encloses. But, goes the
counter-argument, such a measurement would need to consider the pen
size, so the status quo is proper. If you want the pixel-touched
measure, you have to add the pen size to the rectangle width.
</p><p>
Eric Berdahl contends that the width+pen_size business is a product of
Be's "center pen" approach. He would like to see Be adopt a more
flexible pen model (i.e. "inset" and "outset" pens).
</p></div><div class="sect3"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id606486"></a>Subject: Be supporting developers</h4></div></div></div><p>
Devtalkers take a step back (or across, or something) and discuss Be's
marketing approach, its seemingly unshakable association with Apple,
whether a brainwash-the-CS- department approach can work, the role of
free and eminently portable software in an OS company's success, and
other non-technical matters that all broached the question: How shall
Be thrive? Lots of opinions, or, at least, a lot of attitudes.
</p><p>
Side-stepping back into the tech stream, another question was raised:
What's a Be app? Does a port count, or is there some other defining
element. Some proposed litmus strips:
</p><ul class="itemizedlist"><li><p>
<code class="classname">BWindow</code>. If you don't have a <code class="classname">BWindow</code>, you're not a Be app.
</p></li><li><p>
<code class="classname">BMessage</code>s. Non-UI apps (servers) can still qualify if they
respond to <code class="classname">BMessage</code>s.
</p></li></ul></div></div></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="Issue2-46.html">Issue 2-46, November 19, 1997</a>  Up: <a href="volume2.html">Volume 2: 1997</a>  Next: <a href="Issue2-48.html">Issue 2-48, December 3, 1997</a> </div><div id="footerB"><div id="footerBL"><a href="Issue2-46.html" title="Issue 2-46, November 19, 1997"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="volume2.html" title="Volume 2: 1997"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="Issue2-48.html" title="Issue 2-48, December 3, 1997"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="footerBR"><div><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div></div><div id="footerBC"><a href="http://www.access-company.com/home.html" title="ACCESS Co."><img alt="Access Company" src="./images/access_logo.png" /></a></div></div></div><div id="licenseFooter"><div id="licenseFooterBL"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png" /></a></div><div id="licenseFooterBR"><a href="./LegalNotice.html">Legal Notice</a></div><div id="licenseFooterBC"><span id="licenseText">This work is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative
Commons Attribution-Non commercial-No Derivative Works 3.0 License</a>.</span></div></div></body></html>