On Tue, 2005-10-11 at 21:29 -0400, Paul Alfille wrote:
> > > int OW_get( const char * path, char * buffer, int buffer_length ) ;
> >
> > Don't let the programmer specify a buffer length for gets. It's prone to
> > programming errors. The extra malloc() isn't going to cause any real
> > problems, but if you're worried, a:
> >
>
> We could do that, and demand the programmer "free" the buffer. The length
> would be problematic, since some "get" values are binary rather than ascii so
> can't be handled by normal string functions.
Right, then we should use two values:
int OW_get(const char *path,char**buffer,unsigned int *len);
This should be the encouraged interface so that they get the entire
value. If they're sure they can get by with less, they can use
OW_get_buffer().
> The memory allocation choice is purely a matter of style. OW_put will need to
> know the buffer length, however, since some field can get null bytes in their
> binary data. The "char ** buffer" parameter in OW_get can scare people, too.
That's probably why people don't use asprintf().
These people get bugs. Learning to use returned pointers like this makes
for safer code.
> libowcapi currently mirrors the owperl API rather closely. It is an
> admittedly
> sparse API, but targetted at programs where 1-wire performance and features
> are secondary to ease of use. For me, the big advantage is that keeping a
> simple and similar API makes maintainance and documentation far easier.
Perl doesn't have this problem; Perl has a concept of a string. So does
python and Java. C doesn't and when people use C, they frequently make
mistakes.
Helping them avoid mistakes involves:
* allocating for them in the common cases
* don't trust their buffers (!)
* making their program crash lots when broken, and never when correct
That last one is hard, but with small programs and an API that
encourages safe behavior, it's fairly attainable.
I don't think this is simply a matter of style- lots of C programmers
use "style" as an argument to write extremely tricky blocks of code.
The standard C library is used everywhere. It's also not a safe library
to use: fgets() and fread() _frequently_ surprise people. It doesn't
help that these library functions are broken on some machines.
When someone finally finds the need to write a suid program, or a
program that reads from the internet (anonymous), then annoying bugs get
turned into huge security weaknesses.
I'm of the opinion that if char** scares someone, they should be using
tcl or perl or python. If they can get past their fears, they'll be
happier as a result, and will probably do "the right thing" more often.
FS_read() doesn't interact with a file descriptor (for example), so
implementing blocking as described is hard, but one could use:
int OW_get( const char * path, char **buffer, size_t *buffer_length ) {
char *q;
size_t p;
int r;
#define CHUNK 1024
for (q = 0, p = 0;;) {
q = realloc(q, p+CHUNK);
if (!q) return __owc_err_func("OW_get",errno);
r = FS_read(path,q+p,CHUNK,p);
if (r < 0) {
(void)free(q); /* some free() clear errno */
return __owc_err_func("OW_get",r);
}
if (r < 1) break;
if (r < p) {
/* assumes r==p if more */
p += r;
break;
}
}
if (buffer_length)*buffer_length=p;
if (buffer)*buffer=q; else (void)free(q);
return 0;
#undef CHUNK
}
Note the returns changed to refer to __owc_err_func() for error
conditions.
int _ow_error_default(const char *s,int r) {
if (r > 0) { /* errno */
perror(s);
exit(255);
}
/* other critical errors? */
return r;
}
int _ow_error_ansi(const char *s, int r) { return r; }
int (*__owc_err_func)(const char *,int r) = _ow_error_default;
void OW_errors(int(*f)(const char *,int));
int OW_get_buffer(const char *path, char *buffer, size_t size, size_t
off)
{
int r = FS_read(path,buffer,size,off);
if (r == 0) return 0;
return __ow_err_func(r);
}
So blocking/completions isn't a requirement, and might make good
additions to the low-level protocol (when we start talking about file
descriptors) -- AND could benefit TCL and Perl as well.
But note here, that while _YOU_ and _I_ can write these things like
this, people who are using the specified API probably cannot. If they
can, they might as well use OW_get_buffer() and they'll know what
they're doing. If not, they'll use OW_get() which at least WORKS LIKE
the perl and tcl and other apis (or how they could...)
> There is no reason why a C program can't call libow itself, rather than using
> libowcapi as a wrapper. In fact, libowcapi shows how to get started.
....
> If you have interest and a need for the C-API, feel free to modify or start
> another C wrapper targetted at a different set of users. Serg and Peter have
> taken owtcl and owpython under their respective wings .
I'd be happy to. But it sounds like there's some resistance to my think
on this that I'd like to work out first :)
--
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/
-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
Owfs-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/owfs-developers