[packages] new package uboot-env-mmc: hacked in support for reading/writing an uboot...
[packages.git] / lang / php5 / patches / 010-PECL-dio.patch
1 --- /dev/null
2 +++ b/ext/dio/config.m4
3 @@ -0,0 +1,10 @@
4 +dnl
5 +dnl $Id: config.m4 291957 2009-12-10 17:13:14Z cyberspice $
6 +dnl 
7 +
8 +PHP_ARG_ENABLE(dio, whether to enable direct I/O support,
9 +[  --enable-dio            Enable direct I/O support])
10 +
11 +if test "$PHP_DIO" != "no"; then
12 +  PHP_NEW_EXTENSION(dio, dio.c dio_common.c dio_posix.c dio_stream_wrappers.c, $ext_shared)
13 +fi
14 --- /dev/null
15 +++ b/ext/dio/dio.c
16 @@ -0,0 +1,871 @@
17 +/*
18 +   +----------------------------------------------------------------------+
19 +   | PHP Version 5                                                        |
20 +   +----------------------------------------------------------------------+
21 +   | Copyright (c) 1997-2009 The PHP Group                                |
22 +   +----------------------------------------------------------------------+
23 +   | This source file is subject to version 3.0 of the PHP license,       |
24 +   | that is bundled with this package in the file LICENSE, and is        |
25 +   | available through the world-wide-web at the following url:           |
26 +   | http://www.php.net/license/3_0.txt.                                  |
27 +   | If you did not receive a copy of the PHP license and are unable to   |
28 +   | obtain it through the world-wide-web, please send a note to          |
29 +   | license@php.net so we can mail you a copy immediately.               |
30 +   +----------------------------------------------------------------------+
31 +   | Author: Sterling Hughes <sterling@php.net>                           |
32 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |
33 +   +----------------------------------------------------------------------+
34 + */
35 +
36 +#ifdef HAVE_CONFIG_H
37 +#include "config.h"
38 +#endif
39 +
40 +#include "php.h"
41 +#include "php_ini.h"
42 +#include "ext/standard/info.h"
43 +
44 +#include "php_dio.h"
45 +#include "php_dio_stream_wrappers.h"
46 +
47 +#include <sys/stat.h>
48 +#include <sys/types.h>
49 +
50 +#ifdef HAVE_UNISTD_H
51 +#include <unistd.h>
52 +#endif
53 +
54 +#include <fcntl.h>
55 +#ifndef PHP_WIN32
56 +#include <termios.h>
57 +#endif
58 +
59 +/* e.g. IRIX does not have CRTSCTS */
60 +#ifndef CRTSCTS
61 +# ifdef CNEW_RTSCTS
62 +#  define CRTSCTS CNEW_RTSCTS
63 +# else
64 +#  define CRTSCTS 0
65 +# endif /* CNEW_RTSCTS */
66 +#endif /* !CRTSCTS */
67 +
68 +/*
69 +   +----------------------------------------------------------------------+
70 +   |                       DEPRECATED FUNCTIONALITY                       |
71 +   +----------------------------------------------------------------------+
72 +   | The functions below are from the earlier DIO versions.  They will    |
73 +   | continue to be maintained but not extended.  It is thoroughly        |
74 +   | recommended that you should use either the stream wrappers or the    |
75 +   | DIO classes in new code. - Melanie                                   |
76 +   +----------------------------------------------------------------------+
77 + */
78 +
79 +#define le_fd_name "Direct I/O File Descriptor"
80 +static int le_fd;
81 +
82 +static int new_php_fd(php_fd_t **f, int fd)
83 +{
84 +       if (!(*f = malloc(sizeof(php_fd_t)))) {
85 +               return 0;
86 +       }
87 +       (*f)->fd = fd;
88 +       return 1;
89 +}
90 +
91 +static void _dio_close_fd(zend_rsrc_list_entry *rsrc TSRMLS_DC)
92 +{
93 +       php_fd_t *f = (php_fd_t *) rsrc->ptr;
94 +       if (f) {
95 +               close(f->fd);
96 +               free(f);
97 +       }
98 +}
99 +
100 +/* {{{ proto resource dio_open(string filename, int flags[, int mode])
101 +   Open a new filename with specified permissions of flags and creation permissions of mode */
102 +PHP_FUNCTION(dio_open)
103 +{
104 +       php_fd_t *f;
105 +       char     *file_name;
106 +       int       file_name_length;
107 +       long      flags;
108 +       long      mode = 0;
109 +       int       fd;
110 +
111 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &file_name, &file_name_length, &flags, &mode) == FAILURE) {
112 +               return;
113 +       }
114 +
115 +       if (php_check_open_basedir(file_name TSRMLS_CC) || DIO_SAFE_MODE_CHECK(file_name, "wb+")) {
116 +               RETURN_FALSE;
117 +       }
118 +
119 +       if (ZEND_NUM_ARGS() == 3) {
120 +               fd = open(file_name, flags, mode);
121 +       } else {
122 +               fd = open(file_name, flags);
123 +       }
124 +
125 +       if (fd == -1) {
126 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot open file %s with flags %ld and permissions %ld: %s", file_name, flags, mode, strerror(errno));
127 +               RETURN_FALSE;
128 +       }
129 +
130 +       if (!new_php_fd(&f, fd)) {
131 +               RETURN_FALSE;
132 +       }
133 +
134 +       ZEND_REGISTER_RESOURCE(return_value, f, le_fd);
135 +}
136 +/* }}} */
137 +
138 +#ifndef PHP_WIN32
139 +
140 +/* {{{ proto resource dio_fdopen(int fd)
141 +   Returns a resource for the specified file descriptor. */
142 +PHP_FUNCTION(dio_fdopen)
143 +{
144 +       php_fd_t *f;
145 +       long lfd;
146 +       int fd;
147 +
148 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lfd) == FAILURE) {
149 +               return;
150 +       }
151 +
152 +       fd = (int)lfd;
153 +
154 +       if ((fcntl(fd, F_GETFL, 0) == -1) && (errno == EBADF)) {
155 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad file descriptor %d", fd);
156 +               RETURN_FALSE;
157 +       }
158 +
159 +       if (!new_php_fd(&f, fd)) {
160 +               RETURN_FALSE;
161 +       }
162 +
163 +       ZEND_REGISTER_RESOURCE(return_value, f, le_fd);
164 +}
165 +/* }}} */
166 +
167 +
168 +/* {{{ proto resource dio_dup(resource fd)
169 +   Opens a duplicate of the specified open resource. */
170 +PHP_FUNCTION(dio_dup)
171 +{
172 +       zval     *r_fd;
173 +       php_fd_t *f, *df;
174 +       int dfd;
175 +
176 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) {
177 +               return;
178 +       }
179 +
180 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
181 +
182 +       dfd = dup(f->fd);
183 +       if (dfd == -1) {
184 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot duplication file descriptor %d: %s", f->fd, strerror(errno));
185 +               RETURN_FALSE;
186 +       }
187 +
188 +       if (!new_php_fd(&df, dfd)) {
189 +               RETURN_FALSE;
190 +       }
191 +
192 +       ZEND_REGISTER_RESOURCE(return_value, df, le_fd);
193 +}
194 +/* }}} */
195 +#endif
196 +
197 +/* {{{ proto string dio_read(resource fd[, int n])
198 +   Read n bytes from fd and return them, if n is not specified, read 1k */
199 +PHP_FUNCTION(dio_read)
200 +{
201 +       zval     *r_fd;
202 +       php_fd_t *f;
203 +       char     *data;
204 +       long      bytes = 1024;
205 +       ssize_t   res;
206 +
207 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &r_fd, &bytes) == FAILURE) {
208 +               return;
209 +       }
210 +
211 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
212 +
213 +       if (bytes <= 0) {
214 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0.");
215 +               RETURN_FALSE;
216 +       }
217 +
218 +       data = emalloc(bytes + 1);
219 +       res = read(f->fd, data, bytes);
220 +       if (res <= 0) {
221 +               efree(data);
222 +               RETURN_NULL();
223 +       }
224 +
225 +       data = erealloc(data, res + 1);
226 +       data[res] = 0;
227 +
228 +       RETURN_STRINGL(data, res, 0);
229 +}
230 +/* }}} */
231 +
232 +/* {{{ proto int dio_write(resource fd, string data[, int len])
233 +   Write data to fd with optional truncation at length */
234 +PHP_FUNCTION(dio_write)
235 +{
236 +       zval     *r_fd;
237 +       php_fd_t *f;
238 +       char     *data;
239 +       int       data_len;
240 +       long      trunc_len = 0;
241 +       ssize_t   res;
242 +
243 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &r_fd, &data, &data_len, &trunc_len) == FAILURE) {
244 +               return;
245 +       }
246 +
247 +       if (trunc_len < 0 || trunc_len > data_len) {
248 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater or equal to zero and less then the length of the specified string.");
249 +               RETURN_FALSE;
250 +       }
251 +
252 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
253 +
254 +       res = write(f->fd, data, trunc_len ? trunc_len : data_len);
255 +       if (res == -1) {
256 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write data to file descriptor %d: %s", f->fd, strerror(errno));
257 +       }
258 +
259 +       RETURN_LONG(res);
260 +}
261 +/* }}} */
262 +
263 +#ifndef PHP_WIN32
264 +
265 +/* {{{ proto bool dio_truncate(resource fd, int offset)
266 +   Truncate file descriptor fd to offset bytes */
267 +PHP_FUNCTION(dio_truncate)
268 +{
269 +       zval     *r_fd;
270 +       php_fd_t *f;
271 +       long      offset;
272 +
273 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &r_fd, &offset) == FAILURE) {
274 +               return;
275 +       }
276 +
277 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
278 +
279 +       if (ftruncate(f->fd, offset) == -1) {
280 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "couldn't truncate %d to %ld bytes: %s", f->fd, offset, strerror(errno));
281 +               RETURN_FALSE;
282 +       }
283 +
284 +       RETURN_TRUE;
285 +}
286 +/* }}} */
287 +#endif
288 +
289 +#define ADD_FIELD(f, v) add_assoc_long_ex(return_value, (f), sizeof(f), v);
290 +
291 +/* {{{ proto array dio_stat(resource fd)
292 +   Get stat information about the file descriptor fd */
293 +PHP_FUNCTION(dio_stat)
294 +{
295 +       zval        *r_fd;
296 +       php_fd_t    *f;
297 +       struct stat  s;
298 +
299 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) {
300 +               return;
301 +       }
302 +
303 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
304 +
305 +       if (fstat(f->fd, &s) == -1) {
306 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot stat %d: %s", f->fd, strerror(errno));
307 +               RETURN_FALSE;
308 +       }
309 +
310 +       array_init(return_value);
311 +       ADD_FIELD("device", s.st_dev);
312 +       ADD_FIELD("inode", s.st_ino);
313 +       ADD_FIELD("mode", s.st_mode);
314 +       ADD_FIELD("nlink", s.st_nlink);
315 +       ADD_FIELD("uid", s.st_uid);
316 +       ADD_FIELD("gid", s.st_gid);
317 +       ADD_FIELD("device_type", s.st_rdev);
318 +       ADD_FIELD("size", s.st_size);
319 +#ifndef PHP_WIN32
320 +       ADD_FIELD("block_size", s.st_blksize);
321 +       ADD_FIELD("blocks", s.st_blocks);
322 +#endif
323 +       ADD_FIELD("atime", s.st_atime);
324 +       ADD_FIELD("mtime", s.st_mtime);
325 +       ADD_FIELD("ctime", s.st_ctime);
326 +}
327 +/* }}} */
328 +
329 +/* {{{ proto int dio_seek(resource fd, int pos, int whence)
330 +   Seek to pos on fd from whence */
331 +PHP_FUNCTION(dio_seek)
332 +{
333 +       zval     *r_fd;
334 +       php_fd_t *f;
335 +       long      offset;
336 +       long      whence = SEEK_SET;
337 +
338 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &r_fd, &offset, &whence) == FAILURE) {
339 +               return;
340 +       }
341 +
342 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
343 +
344 +       RETURN_LONG(lseek(f->fd, offset, whence));
345 +}
346 +/* }}} */
347 +
348 +#ifndef PHP_WIN32
349 +
350 +/* {{{ proto mixed dio_fcntl(resource fd, int cmd[, mixed arg])
351 +   Perform a c library fcntl on fd */
352 +PHP_FUNCTION(dio_fcntl)
353 +{
354 +       zval     *r_fd;
355 +       zval     *arg = NULL;
356 +       php_fd_t *f;
357 +       long      cmd;
358 +
359 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &r_fd, &cmd, &arg) == FAILURE) {
360 +               return;
361 +       }
362 +
363 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
364 +
365 +       switch (cmd) {
366 +               case F_SETLK:
367 +               case F_SETLKW: {
368 +                       zval          **element;
369 +                       struct flock    lk = {0};
370 +                       HashTable      *fh;
371 +
372 +                       if (!arg) {
373 +                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be array or int, none given");
374 +                               RETURN_FALSE;
375 +                       }
376 +                       if (Z_TYPE_P(arg) == IS_ARRAY) {
377 +                               fh = HASH_OF(arg);
378 +                               if (zend_hash_find(fh, "start", sizeof("start"), (void **) &element) == FAILURE) {
379 +                                       lk.l_start = 0;
380 +                               } else {
381 +                                       lk.l_start = Z_LVAL_PP(element);
382 +                               }
383 +
384 +                               if (zend_hash_find(fh, "length", sizeof("length"), (void **) &element) == FAILURE) {
385 +                                       lk.l_len = 0;
386 +                               } else {
387 +                                       lk.l_len = Z_LVAL_PP(element);
388 +                               }
389 +
390 +                               if (zend_hash_find(fh, "whence", sizeof("whence"), (void **) &element) == FAILURE) {
391 +                                       lk.l_whence = 0;
392 +                               } else {
393 +                                       lk.l_whence = Z_LVAL_PP(element);
394 +                               }
395 +
396 +                               if (zend_hash_find(fh, "type", sizeof("type"), (void **) &element) == FAILURE) {
397 +                                       lk.l_type = 0;
398 +                               } else {
399 +                                       lk.l_type = Z_LVAL_PP(element);
400 +                               }
401 +                       } else if (Z_TYPE_P(arg) == IS_LONG) {
402 +                               lk.l_start  = 0;
403 +                               lk.l_len    = 0;
404 +                               lk.l_whence = SEEK_SET;
405 +                               lk.l_type   = Z_LVAL_P(arg);
406 +                       } else {
407 +                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be array or int, %s given", zend_zval_type_name(arg));
408 +                               RETURN_FALSE;
409 +                       }
410 +
411 +                       RETURN_LONG(fcntl(f->fd, cmd, &lk));
412 +                       break;
413 +               }
414 +               case F_GETLK: {
415 +                       struct flock lk = {0};
416 +
417 +                       fcntl(f->fd, cmd, &lk);
418 +
419 +                       array_init(return_value);
420 +                       add_assoc_long(return_value, "type", lk.l_type);
421 +                       add_assoc_long(return_value, "whence", lk.l_whence);
422 +                       add_assoc_long(return_value, "start", lk.l_start);
423 +                       add_assoc_long(return_value, "length", lk.l_len);
424 +                       add_assoc_long(return_value, "pid", lk.l_pid);
425 +
426 +                       break;
427 +               }
428 +               case F_DUPFD: {
429 +                       php_fd_t *new_f;
430 +
431 +                       if (!arg || Z_TYPE_P(arg) != IS_LONG) {
432 +                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be int");
433 +                               RETURN_FALSE;
434 +                       }
435 +
436 +                       if (!new_php_fd(&new_f, fcntl(f->fd, cmd, Z_LVAL_P(arg)))) {
437 +                               RETURN_FALSE;
438 +                       }
439 +                       ZEND_REGISTER_RESOURCE(return_value, new_f, le_fd);
440 +                       break;
441 +               }
442 +               default:
443 +                       if (!arg || Z_TYPE_P(arg) != IS_LONG) {
444 +                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be int");
445 +                               RETURN_FALSE;
446 +                       }
447 +
448 +                       RETURN_LONG(fcntl(f->fd, cmd, Z_LVAL_P(arg)));
449 +       }
450 +}
451 +/* }}} */
452 +#endif
453 +
454 +#ifndef PHP_WIN32
455 +
456 +/* {{{ proto mixed dio_tcsetattr(resource fd,  array args )
457 +   Perform a c library tcsetattr on fd */
458 +PHP_FUNCTION(dio_tcsetattr)
459 +{
460 +       zval     *r_fd;
461 +       zval     *arg = NULL;
462 +       php_fd_t *f;
463 +       struct termios newtio;
464 +       int Baud_Rate, Data_Bits=8, Stop_Bits=1, Parity=0, Flow_Control=1, Is_Canonical=1;
465 +       long BAUD,DATABITS,STOPBITS,PARITYON,PARITY;
466 +       HashTable      *fh;
467 +       zval          **element;
468 +
469 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &r_fd, &arg) == FAILURE) {
470 +               return;
471 +       }
472 +
473 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
474 +
475 +       if (Z_TYPE_P(arg) != IS_ARRAY) {
476 +               php_error_docref(NULL TSRMLS_CC, E_WARNING,"tcsetattr, third argument should be an associative array");
477 +               return;
478 +       }
479 +
480 +       fh = HASH_OF(arg);
481 +
482 +       if (zend_hash_find(fh, "baud", sizeof("baud"), (void **) &element) == FAILURE) {
483 +               Baud_Rate = 9600;
484 +       } else {
485 +               Baud_Rate = Z_LVAL_PP(element);
486 +       }
487 +
488 +       if (zend_hash_find(fh, "bits", sizeof("bits"), (void **) &element) == FAILURE) {
489 +               Data_Bits = 8;
490 +       } else {
491 +               Data_Bits = Z_LVAL_PP(element);
492 +       }
493 +
494 +       if (zend_hash_find(fh, "stop", sizeof("stop"), (void **) &element) == FAILURE) {
495 +               Stop_Bits = 1;
496 +       } else {
497 +               Stop_Bits = Z_LVAL_PP(element);
498 +       }
499 +
500 +       if (zend_hash_find(fh, "parity", sizeof("parity"), (void **) &element) == FAILURE) {
501 +               Parity = 0;
502 +       } else {
503 +               Parity = Z_LVAL_PP(element);
504 +       }
505 +
506 +       if (zend_hash_find(fh, "flow_control", sizeof("flow_control"), (void **) &element) == FAILURE) {
507 +               Flow_Control = 1;
508 +       } else {
509 +               Flow_Control = Z_LVAL_PP(element);
510 +       }
511 +
512 +       if (zend_hash_find(fh, "is_canonical", sizeof("is_canonical"), (void **) &element) == FAILURE) {
513 +               Is_Canonical = 0;
514 +       } else {
515 +               Is_Canonical = Z_LVAL_PP(element);
516 +       }
517 +
518 +       /* assign to correct values... */
519 +       switch (Baud_Rate)  {
520 +               case 38400:
521 +                       BAUD = B38400;
522 +                       break;
523 +               case 19200:
524 +                       BAUD = B19200;
525 +                       break;
526 +               case 9600:
527 +                       BAUD = B9600;
528 +                       break;
529 +               case 4800:
530 +                       BAUD = B4800;
531 +                       break;
532 +               case 2400:
533 +                       BAUD = B2400;
534 +                       break;
535 +               case 1800:
536 +                       BAUD = B1800;
537 +                       break;
538 +               case 1200:
539 +                       BAUD = B1200;
540 +                       break;
541 +               case 600:
542 +                       BAUD = B600;
543 +                       break;
544 +               case 300:
545 +                       BAUD = B300;
546 +                       break;
547 +               case 200:
548 +                       BAUD = B200;
549 +                       break;
550 +               case 150:
551 +                       BAUD = B150;
552 +                       break;
553 +               case 134:
554 +                       BAUD = B134;
555 +                       break;
556 +               case 110:
557 +                       BAUD = B110;
558 +                       break;
559 +               case 75:
560 +                       BAUD = B75;
561 +                       break;
562 +               case 50:
563 +                       BAUD = B50;
564 +                       break;
565 +               default:
566 +                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid baud rate %d", Baud_Rate);
567 +                       RETURN_FALSE;
568 +       }
569 +       switch (Data_Bits) {
570 +               case 8:
571 +                       DATABITS = CS8;
572 +                       break;
573 +               case 7:
574 +                       DATABITS = CS7;
575 +                       break;
576 +               case 6:
577 +                       DATABITS = CS6;
578 +                       break;
579 +               case 5:
580 +                       DATABITS = CS5;
581 +                       break;
582 +               default:
583 +                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data bits %d", Data_Bits);
584 +                       RETURN_FALSE;
585 +       }
586 +       switch (Stop_Bits) {
587 +               case 1:
588 +                       STOPBITS = 0;
589 +                       break;
590 +               case 2:
591 +                       STOPBITS = CSTOPB;
592 +                       break;
593 +               default:
594 +                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop bits %d", Stop_Bits);
595 +                       RETURN_FALSE;
596 +       }
597 +
598 +       switch (Parity) {
599 +               case 0:
600 +                       PARITYON = 0;
601 +                       PARITY = 0;
602 +                       break;
603 +               case 1:
604 +                       PARITYON = PARENB;
605 +                       PARITY = PARODD;
606 +                       break;
607 +               case 2:
608 +                       PARITYON = PARENB;
609 +                       PARITY = 0;
610 +                       break;
611 +               default:
612 +                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity %d", Parity);
613 +                       RETURN_FALSE;
614 +       }
615 +
616 +       memset(&newtio, 0, sizeof(newtio));
617 +       tcgetattr(f->fd, &newtio);
618 +
619 +       if (Is_Canonical) {
620 +               newtio.c_iflag = IGNPAR | ICRNL;
621 +               newtio.c_oflag = 0;
622 +               newtio.c_lflag = ICANON;
623 +       } else {
624 +               cfmakeraw(&newtio);
625 +       }
626 +
627 +       newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
628 +
629 +#ifdef CRTSCTS
630 +       if (Flow_Control) {
631 +               newtio.c_cflag |= CRTSCTS;
632 +       }
633 +#endif
634 +
635 +       if (Is_Canonical)
636 +
637 +       newtio.c_cc[VMIN] = 1;
638 +       newtio.c_cc[VTIME] = 0;
639 +       tcflush(f->fd, TCIFLUSH);
640 +       tcsetattr(f->fd,TCSANOW,&newtio);
641 +
642 +       RETURN_TRUE;
643 +}
644 +/* }}} */
645 +#endif
646 +
647 +/* {{{ proto void dio_close(resource fd)
648 +   Close the file descriptor given by fd */
649 +PHP_FUNCTION(dio_close)
650 +{
651 +       zval     *r_fd;
652 +       php_fd_t *f;
653 +
654 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) {
655 +               return;
656 +       }
657 +
658 +       ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd);
659 +
660 +       zend_list_delete(Z_LVAL_P(r_fd));
661 +}
662 +/* }}} */
663 +
664 +#define RDIOC(c) REGISTER_LONG_CONSTANT(#c, c, CONST_CS | CONST_PERSISTENT)
665 +
666 +/* {{{ dio_init_legacy_defines
667 + * Initialises the legacy PHP defines
668 + */
669 +static void dio_init_legacy_defines(int module_number TSRMLS_DC) {
670 +       RDIOC(O_RDONLY);
671 +       RDIOC(O_WRONLY);
672 +       RDIOC(O_RDWR);
673 +       RDIOC(O_CREAT);
674 +       RDIOC(O_EXCL);
675 +       RDIOC(O_TRUNC);
676 +       RDIOC(O_APPEND);
677 +#ifdef O_NONBLOCK
678 +       RDIOC(O_NONBLOCK);
679 +#endif
680 +#ifdef O_NDELAY
681 +       RDIOC(O_NDELAY);
682 +#endif
683 +#ifdef O_SYNC
684 +       RDIOC(O_SYNC);
685 +#endif
686 +#ifdef O_ASYNC
687 +       RDIOC(O_ASYNC);
688 +#endif
689 +#ifdef O_NOCTTY
690 +       RDIOC(O_NOCTTY);
691 +#endif
692 +#ifndef PHP_WIN32
693 +       RDIOC(S_IRWXU);
694 +       RDIOC(S_IRUSR);
695 +       RDIOC(S_IWUSR);
696 +       RDIOC(S_IXUSR);
697 +       RDIOC(S_IRWXG);
698 +       RDIOC(S_IRGRP);
699 +       RDIOC(S_IWGRP);
700 +       RDIOC(S_IXGRP);
701 +       RDIOC(S_IRWXO);
702 +       RDIOC(S_IROTH);
703 +       RDIOC(S_IWOTH);
704 +       RDIOC(S_IXOTH);
705 +       RDIOC(F_DUPFD);
706 +       RDIOC(F_GETFD);
707 +       RDIOC(F_GETFL);
708 +       RDIOC(F_SETFL);
709 +       RDIOC(F_GETLK);
710 +       RDIOC(F_SETLK);
711 +       RDIOC(F_SETLKW);
712 +       RDIOC(F_SETOWN);
713 +       RDIOC(F_GETOWN);
714 +       RDIOC(F_UNLCK);
715 +       RDIOC(F_RDLCK);
716 +       RDIOC(F_WRLCK);
717 +#endif
718 +}
719 +
720 +ZEND_BEGIN_ARG_INFO_EX(dio_open_args, 0, 0, 2)
721 +       ZEND_ARG_INFO(0, filename)
722 +       ZEND_ARG_INFO(0, flags)
723 +       ZEND_ARG_INFO(0, mode)
724 +ZEND_END_ARG_INFO()
725 +
726 +ZEND_BEGIN_ARG_INFO_EX(dio_fdopen_args, 0, 0, 1)
727 +       ZEND_ARG_INFO(0, fd)
728 +ZEND_END_ARG_INFO()
729 +
730 +ZEND_BEGIN_ARG_INFO_EX(dio_dup_args, 0, 0, 1)
731 +       ZEND_ARG_INFO(0, fd)
732 +ZEND_END_ARG_INFO()
733 +
734 +
735 +ZEND_BEGIN_ARG_INFO_EX(dio_read_args, 0, 0, 1)
736 +       ZEND_ARG_INFO(0, fd)
737 +       ZEND_ARG_INFO(0, n)
738 +ZEND_END_ARG_INFO()
739 +
740 +ZEND_BEGIN_ARG_INFO_EX(dio_write_args, 0, 0, 2)
741 +       ZEND_ARG_INFO(0, fd)
742 +       ZEND_ARG_INFO(0, data)
743 +       ZEND_ARG_INFO(0, len)
744 +ZEND_END_ARG_INFO()
745 +
746 +ZEND_BEGIN_ARG_INFO_EX(dio_stat_args, 0, 0, 1)
747 +       ZEND_ARG_INFO(0, fd)
748 +ZEND_END_ARG_INFO()
749 +
750 +ZEND_BEGIN_ARG_INFO_EX(dio_truncate_args, 0, 0, 2)
751 +       ZEND_ARG_INFO(0, fd)
752 +       ZEND_ARG_INFO(0, offset)
753 +ZEND_END_ARG_INFO()
754 +
755 +ZEND_BEGIN_ARG_INFO_EX(dio_seek_args, 0, 0, 3)
756 +       ZEND_ARG_INFO(0, fd)
757 +       ZEND_ARG_INFO(0, pos)
758 +       ZEND_ARG_INFO(0, whence)
759 +ZEND_END_ARG_INFO()
760 +
761 +ZEND_BEGIN_ARG_INFO_EX(dio_fcntl_args, 0, 0, 2)
762 +       ZEND_ARG_INFO(0, fd)
763 +       ZEND_ARG_INFO(0, cmd)
764 +       ZEND_ARG_INFO(0, arg)
765 +ZEND_END_ARG_INFO()
766 +
767 +ZEND_BEGIN_ARG_INFO_EX(dio_tcsetattr_args, 0, 0, 2)
768 +       ZEND_ARG_INFO(0, fd)
769 +       ZEND_ARG_INFO(0, args)
770 +ZEND_END_ARG_INFO()
771 +
772 +ZEND_BEGIN_ARG_INFO_EX(dio_close_args, 0, 0, 1)
773 +       ZEND_ARG_INFO(0, fd)
774 +ZEND_END_ARG_INFO()
775 +
776 +/*
777 +   +----------------------------------------------------------------------+
778 +   |                   END OF DEPRECATED FUNCTIONALITY                    |
779 +   +----------------------------------------------------------------------+
780 + */
781 +
782 +ZEND_BEGIN_ARG_INFO_EX(dio_raw_args, 0, 0, 2)
783 +       ZEND_ARG_INFO(0, filename)
784 +       ZEND_ARG_INFO(0, mode)
785 +       ZEND_ARG_INFO(0, options)
786 +ZEND_END_ARG_INFO()
787 +
788 +ZEND_BEGIN_ARG_INFO_EX(dio_serial_args, 0, 0, 2)
789 +       ZEND_ARG_INFO(0, filename)
790 +       ZEND_ARG_INFO(0, mode)
791 +       ZEND_ARG_INFO(0, options)
792 +ZEND_END_ARG_INFO()
793 +
794 +static zend_object_handlers dio_raw_object_handlers;
795 +
796 +static zend_function_entry dio_functions[] = {
797 +       /* Class functions. */
798 +
799 +       /* Legacy functions (Deprecated - See dio_legacy.c) */
800 +       PHP_FE(dio_open, dio_open_args)
801 +#ifndef PHP_WIN32
802 +       PHP_FE(dio_fdopen, dio_fdopen_args)
803 +       PHP_FE(dio_dup, dio_dup_args)
804 +       PHP_FE(dio_truncate, dio_truncate_args)
805 +#endif
806 +       PHP_FE(dio_stat, dio_stat_args)
807 +       PHP_FE(dio_seek, dio_seek_args)
808 +#ifndef PHP_WIN32
809 +       PHP_FE(dio_fcntl, dio_fcntl_args)
810 +#endif
811 +       PHP_FE(dio_read, dio_read_args)
812 +       PHP_FE(dio_write, dio_write_args)
813 +       PHP_FE(dio_close, dio_close_args)
814 +#ifndef PHP_WIN32
815 +       PHP_FE(dio_tcsetattr, dio_tcsetattr_args)
816 +#endif
817 +
818 +       /* Stream functions */
819 +       PHP_FE(dio_raw, dio_raw_args)
820 +       PHP_FE(dio_serial, dio_serial_args)
821 +
822 +       /* End of functions */
823 +       {NULL, NULL, NULL}
824 +};
825 +
826 +zend_module_entry dio_module_entry = {
827 +       STANDARD_MODULE_HEADER,
828 +       "dio",
829 +       dio_functions,
830 +       PHP_MINIT(dio),
831 +       NULL,
832 +       NULL,   
833 +       NULL,
834 +       PHP_MINFO(dio),
835 +       PHP_DIO_VERSION,
836 +       STANDARD_MODULE_PROPERTIES
837 +};
838 +
839 +#ifdef COMPILE_DL_DIO
840 +ZEND_GET_MODULE(dio)
841 +#endif
842 +
843 +#define DIO_UNDEF_CONST -1
844 +
845 +/* {{{ PHP_MINIT_FUNCTION
846 + */
847 +PHP_MINIT_FUNCTION(dio)
848 +{
849 +       /* Legacy resource destructor. */
850 +       le_fd = zend_register_list_destructors_ex(_dio_close_fd, NULL, le_fd_name, module_number);
851 +
852 +       dio_init_legacy_defines(module_number TSRMLS_CC);
853 +
854 +       /* Register the stream wrappers */
855 +       return (php_register_url_stream_wrapper(DIO_RAW_STREAM_NAME, &php_dio_raw_stream_wrapper TSRMLS_CC) == SUCCESS &&
856 +                       php_register_url_stream_wrapper(DIO_SERIAL_STREAM_NAME, &php_dio_serial_stream_wrapper TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE;
857 +}
858 +/* }}} */
859 +
860 +/* {{{ PHP_MSHUTDOWN_FUNCTION
861 + */
862 +PHP_MSHUTDOWN_FUNCTION(dio)
863 +{
864 +       return (php_unregister_url_stream_wrapper(DIO_RAW_STREAM_NAME TSRMLS_CC) == SUCCESS &&
865 +                       php_unregister_url_stream_wrapper(DIO_SERIAL_STREAM_NAME TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE;
866 +}
867 +/* }}} */
868 +
869 +/* {{{ PHP_MINFO_FUNCTION
870 + */
871 +PHP_MINFO_FUNCTION(dio)
872 +{
873 +       php_info_print_table_start();
874 +       php_info_print_table_header(2, "dio support", "enabled");
875 +       php_info_print_table_row(2, "version", PHP_DIO_VERSION);
876 +       php_info_print_table_end();
877 +}
878 +/* }}} */
879 +
880 +/*
881 + * Local variables:
882 + * c-basic-offset: 4
883 + * tab-width: 4
884 + * End:
885 + * vim600: fdm=marker
886 + * vim: sw=4 ts=4 noet
887 + */
888 --- /dev/null
889 +++ b/ext/dio/dio_common.c
890 @@ -0,0 +1,230 @@
891 +/*
892 +   +----------------------------------------------------------------------+
893 +   | PHP Version 5                                                        |
894 +   +----------------------------------------------------------------------+
895 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |
896 +   +----------------------------------------------------------------------+
897 +   | This source file is subject to version 3.0 of the PHP license,       |
898 +   | that is bundled with this package in the file LICENSE, and is        |
899 +   | available through the world-wide-web at the following url:           |
900 +   | http://www.php.net/license/3_0.txt.                                  |
901 +   | If you did not receive a copy of the PHP license and are unable to   |
902 +   | obtain it through the world-wide-web, please send a note to          |
903 +   | license@php.net so we can mail you a copy immediately.               |
904 +   +----------------------------------------------------------------------+
905 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |
906 +   +----------------------------------------------------------------------+
907 + */
908 +
909 +#ifdef HAVE_CONFIG_H
910 +#include "config.h"
911 +#endif
912 +
913 +#include "php.h"
914 +
915 +#include "php_dio.h"
916 +#include "php_dio_common.h"
917 +
918 +/* {{{ dio_init_stream_data
919 + * Initialises the command parts of the stream data.
920 + */
921 +void dio_init_stream_data(php_dio_stream_data *data) {
922 +       data->stream_type = DIO_STREAM_TYPE_NONE;
923 +       data->end_of_file = 0;
924 +#ifdef DIO_HAS_FILEPERMS
925 +       data->has_perms = 0;
926 +       data->perms = 0;
927 +#endif
928 +#ifdef DIO_NONBLOCK
929 +       data->is_blocking = 1;
930 +       data->has_timeout = 0;
931 +       data->timeout_sec = 0;
932 +       data->timeout_usec = 0;
933 +       data->timed_out = 0;
934 +#endif
935 +       /* Serial options */
936 +       data->data_rate = 9600;
937 +       data->data_bits = 8;
938 +       data->stop_bits = 1;
939 +       data->parity = 0;
940 +       data->flow_control = 1;
941 +       data->canonical = 1;
942 +}
943 +/* }}} */
944 +
945 +/* {{{ dio_convert_to_long
946 + * Returns as a long, the value of the zval regardless of its type.
947 + */
948 +long dio_convert_to_long(zval *val) {
949 +       zval *copyval;
950 +       long  longval;
951 +
952 +       ALLOC_INIT_ZVAL(copyval);
953 +       *copyval = *val;
954 +       convert_to_long(copyval);
955 +       longval = Z_LVAL_P(copyval);
956 +       zval_ptr_dtor(&copyval);
957 +
958 +       return longval;
959 +}
960 +/* }}} */
961 +
962 +/* {{{ dio_assoc_array_get_basic_options
963 + * Retrieves the basic open option values from an associative array
964 + */
965 +void dio_assoc_array_get_basic_options(zval *options, php_dio_stream_data *data TSRMLS_DC) {
966 +#if defined(DIO_HAS_FILEPERMS) || defined(DIO_NONBLOCK)
967 +       zval **tmpzval;
968 +       HashTable *opthash;
969 +
970 +       opthash = HASH_OF(options);
971 +#endif
972 +
973 +#ifdef DIO_HAS_FILEPERMS
974 +       /* This is the file mode flags used by open(). */
975 +       if (zend_hash_find(opthash, "perms", sizeof("perms"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
976 +               data->perms = (int)dio_convert_to_long(*tmpzval);
977 +               data->has_perms = 1;
978 +       }
979 +#endif
980 +
981 +#ifdef DIO_NONBLOCK
982 +       /* This sets the underlying stream to be blocking/non
983 +          block (i.e. O_NONBLOCK) */
984 +       if (zend_hash_find(opthash, "is_blocking", sizeof("is_blocking"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
985 +               data->is_blocking = dio_convert_to_long(*tmpzval) ? 1 : 0;
986 +       }
987 +
988 +       /* This is the timeout value for reads in seconds.  Only one of
989 +          timeout_secs or timeout_usecs need be defined to define a timeout. */
990 +       if (zend_hash_find(opthash, "timeout_secs", sizeof("timeout_secs"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
991 +               data->timeout_sec = dio_convert_to_long(*tmpzval);
992 +       }
993 +
994 +       /* This is the timeout value for reads in microseconds.  Only one of
995 +          timeout_secs or timeout_usecs need be defined to define a timeout. */
996 +       if (zend_hash_find(opthash, "timeout_usecs", sizeof("timeout_usecs"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
997 +               data->timeout_usec = dio_convert_to_long(*tmpzval);
998 +       }
999 +
1000 +       data->has_timeout = (data->timeout_sec | data->timeout_usec) ? 1 : 0;
1001 +#endif
1002 +}
1003 +/* }}} */
1004 +
1005 +/* {{{ dio_assoc_array_get_serial_options
1006 + * Retrieves the serial open option values from an associative array
1007 + */
1008 +void dio_assoc_array_get_serial_options(zval *options, php_dio_stream_data *data TSRMLS_DC) {
1009 +       zval **tmpzval;
1010 +       HashTable *opthash;
1011 +
1012 +       opthash = HASH_OF(options);
1013 +
1014 +       if (zend_hash_find(opthash, "data_rate", sizeof("data_rate"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1015 +               data->data_rate = dio_convert_to_long(*tmpzval);
1016 +       }
1017 +
1018 +       if (zend_hash_find(opthash, "data_bits", sizeof("data_bits"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1019 +               data->data_bits = (int)dio_convert_to_long(*tmpzval);
1020 +       }
1021 +
1022 +       if (zend_hash_find(opthash, "stop_bits", sizeof("stop_bits"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1023 +               data->stop_bits = (int)dio_convert_to_long(*tmpzval);
1024 +       }
1025 +
1026 +       if (zend_hash_find(opthash, "parity", sizeof("parity"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1027 +               data->parity = (int)dio_convert_to_long(*tmpzval);
1028 +       }
1029 +
1030 +       if (zend_hash_find(opthash, "flow_control", sizeof("flow_control"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1031 +               data->flow_control = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0);
1032 +       }
1033 +
1034 +       if (zend_hash_find(opthash, "is_canonical", sizeof("is_canonical"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1035 +               data->canonical = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0);
1036 +       }
1037 +}
1038 +/* }}} */
1039 +
1040 +/* {{{ dio_stream_context_get_raw_options
1041 + * Extracts the option values for dio.raw mode from a context
1042 + */
1043 +void dio_stream_context_get_basic_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC) {
1044 +#if defined(DIO_HAS_FILEPERMS) || defined(DIO_NONBLOCK)
1045 +       zval **tmpzval;
1046 +#endif
1047 +
1048 +#ifdef DIO_HAS_FILEPERMS
1049 +       /* This is the file mode flags used by open(). */
1050 +       if (php_stream_context_get_option(context, "dio", "perms", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1051 +               data->perms = (int)dio_convert_to_long(*tmpzval);
1052 +               data->has_perms = 1;
1053 +       }
1054 +#endif
1055 +
1056 +#ifdef DIO_NONBLOCK
1057 +       /* This sets the underlying stream to be blocking/non
1058 +          block (i.e. O_NONBLOCK) */
1059 +       if (php_stream_context_get_option(context, "dio", "is_blocking", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1060 +               data->is_blocking = dio_convert_to_long(*tmpzval) ? 1 : 0;
1061 +       }
1062 +
1063 +       /* This is the timeout value for reads in seconds.  Only one of
1064 +          timeout_secs or timeout_usecs need be defined to define a timeout. */
1065 +       if (php_stream_context_get_option(context, "dio", "timeout_secs", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1066 +               data->timeout_sec = dio_convert_to_long(*tmpzval);
1067 +       }
1068 +
1069 +       /* This is the timeout value for reads in microseconds.  Only one of
1070 +          timeout_secs or timeout_usecs need be defined to define a timeout. */
1071 +       if (php_stream_context_get_option(context, "dio", "timeout_usecs", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1072 +               data->timeout_usec = dio_convert_to_long(*tmpzval);
1073 +       }
1074 +
1075 +       data->has_timeout = (data->timeout_sec | data->timeout_usec) ? 1 : 0;
1076 +#endif
1077 +}
1078 +/* }}} */
1079 +
1080 +/* {{{ dio_stream_context_get_serial_options
1081 + * Extracts the option values for dio.serial mode from a context
1082 + */
1083 +void dio_stream_context_get_serial_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC) {
1084 +       zval **tmpzval;
1085 +
1086 +       if (php_stream_context_get_option(context, "dio", "data_rate", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1087 +               data->data_rate = dio_convert_to_long(*tmpzval);
1088 +       }
1089 +
1090 +       if (php_stream_context_get_option(context, "dio", "data_bits", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1091 +               data->data_bits = (int)dio_convert_to_long(*tmpzval);
1092 +       }
1093 +
1094 +       if (php_stream_context_get_option(context, "dio", "stop_bits", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1095 +               data->stop_bits = (int)dio_convert_to_long(*tmpzval);
1096 +       }
1097 +
1098 +       if (php_stream_context_get_option(context, "dio", "parity", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1099 +               data->parity = (int)dio_convert_to_long(*tmpzval);
1100 +       }
1101 +
1102 +       if (php_stream_context_get_option(context, "dio", "flow_control", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1103 +               data->flow_control = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0);
1104 +       }
1105 +
1106 +       if (php_stream_context_get_option(context, "dio", "is_canonical", &tmpzval) == SUCCESS && tmpzval && *tmpzval) {
1107 +               data->canonical = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0);
1108 +       }
1109 +}
1110 +/* }}} */
1111 +
1112 +/*
1113 + * Local variables:
1114 + * c-basic-offset: 4
1115 + * tab-width: 4
1116 + * End:
1117 + * vim600: fdm=marker
1118 + * vim: sw=4 ts=4 noet
1119 + */
1120 +
1121 --- /dev/null
1122 +++ b/ext/dio/dio_posix.c
1123 @@ -0,0 +1,659 @@
1124 +/*\r
1125 +   +----------------------------------------------------------------------+\r
1126 +   | PHP Version 5                                                        |\r
1127 +   +----------------------------------------------------------------------+\r
1128 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |\r
1129 +   +----------------------------------------------------------------------+\r
1130 +   | This source file is subject to version 3.0 of the PHP license,       |\r
1131 +   | that is bundled with this package in the file LICENSE, and is        |\r
1132 +   | available through the world-wide-web at the following url:           |\r
1133 +   | http://www.php.net/license/3_0.txt.                                  |\r
1134 +   | If you did not receive a copy of the PHP license and are unable to   |\r
1135 +   | obtain it through the world-wide-web, please send a note to          |\r
1136 +   | license@php.net so we can mail you a copy immediately.               |\r
1137 +   +----------------------------------------------------------------------+\r
1138 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |\r
1139 +   +----------------------------------------------------------------------+\r
1140 + */\r
1141 +\r
1142 +#ifdef HAVE_CONFIG_H\r
1143 +#include "config.h"\r
1144 +#endif\r
1145 +\r
1146 +#include "php.h"\r
1147 +\r
1148 +#include "php_dio_common.h"\r
1149 +\r
1150 +/* {{{ dio_stream_mode_to_flags\r
1151 + * Convert an fopen() mode string to open() flags\r
1152 + */\r
1153 +static int dio_stream_mode_to_flags(const char *mode) {\r
1154 +       int  flags = 0, ch = 0, bin = 1;\r
1155 +\r
1156 +       switch(mode[ch++]) {\r
1157 +               case 'r':\r
1158 +                       flags = 0;\r
1159 +                       break;\r
1160 +               case 'w':\r
1161 +                       flags = O_TRUNC | O_CREAT;\r
1162 +                       break;\r
1163 +               case 'a':\r
1164 +                       flags = O_APPEND | O_CREAT;\r
1165 +                       break;\r
1166 +               case 'x':\r
1167 +                       flags = O_EXCL | O_CREAT;\r
1168 +                       break;\r
1169 +       }\r
1170 +\r
1171 +       if (mode[ch] != '+') {\r
1172 +               bin = (mode[ch++] == 'b');\r
1173 +       }\r
1174 +\r
1175 +       if (mode[ch] == '+') {\r
1176 +               flags |= O_RDWR;\r
1177 +       } else if (flags) {\r
1178 +               flags |= O_WRONLY;\r
1179 +       } else {\r
1180 +               flags |= O_RDONLY;\r
1181 +       }\r
1182 +\r
1183 +#if defined(_O_TEXT) && defined(O_BINARY)\r
1184 +       if (bin) {\r
1185 +               flags |= O_BINARY;\r
1186 +       } else {\r
1187 +               flags |= _O_TEXT;\r
1188 +       }\r
1189 +#endif\r
1190 +\r
1191 +       return flags;\r
1192 +}\r
1193 +/* }}} */\r
1194 +\r
1195 +/* {{{ dio_data_rate_to_define\r
1196 + * Converts a numeric data rate to a termios define\r
1197 + */\r
1198 +static int dio_data_rate_to_define(long rate, speed_t *def) {\r
1199 +       speed_t val;\r
1200 +\r
1201 +       switch (rate) {\r
1202 +               case 0:\r
1203 +                       val = 0;\r
1204 +                       break;\r
1205 +               case 50:\r
1206 +                       val = B50;\r
1207 +                       break;\r
1208 +               case 75:\r
1209 +                       val = B75;\r
1210 +                       break;\r
1211 +               case 110:\r
1212 +                       val = B110;\r
1213 +                       break;\r
1214 +               case 134:\r
1215 +                       val = B134;\r
1216 +                       break;\r
1217 +               case 150:\r
1218 +                       val = B150;\r
1219 +                       break;\r
1220 +               case 200:\r
1221 +                       val = B200;\r
1222 +                       break;\r
1223 +               case 300:\r
1224 +                       val = B300;\r
1225 +                       break;\r
1226 +               case 600:\r
1227 +                       val = B600;\r
1228 +                       break;\r
1229 +               case 1200:\r
1230 +                       val = B1200;\r
1231 +                       break;\r
1232 +               case 1800:\r
1233 +                       val = B1800;\r
1234 +                       break;\r
1235 +               case 2400:\r
1236 +                       val = B2400;\r
1237 +                       break;\r
1238 +               case 4800:\r
1239 +                       val = B4800;\r
1240 +                       break;\r
1241 +               case 9600:\r
1242 +                       val = B9600;\r
1243 +                       break;\r
1244 +               case 19200:\r
1245 +                       val = B19200;\r
1246 +                       break;\r
1247 +               case 38400:\r
1248 +                       val = B38400;\r
1249 +                       break;\r
1250 +#ifdef B57600\r
1251 +               case 57600:\r
1252 +                       val = B57600;\r
1253 +                       break;\r
1254 +#endif\r
1255 +#ifdef B115200\r
1256 +               case 115200:\r
1257 +                       val = B115200;\r
1258 +                       break;\r
1259 +#endif\r
1260 +#ifdef B230400\r
1261 +               case 230400:\r
1262 +                       val = B230400;\r
1263 +                       break;\r
1264 +#endif\r
1265 +#ifdef B460800\r
1266 +               case 460800:\r
1267 +                       val = B460800;\r
1268 +                       break;\r
1269 +#endif\r
1270 +               default:\r
1271 +                       return 0;\r
1272 +       }\r
1273 +\r
1274 +       *def = val;\r
1275 +       return 1;\r
1276 +}\r
1277 +\r
1278 +/* {{{ dio_data_bits_to_define\r
1279 + * Converts a number of data bits to a termios define\r
1280 + */\r
1281 +static int dio_data_bits_to_define(int data_bits, int *def) {\r
1282 +       int val;\r
1283 +\r
1284 +       switch (data_bits) {\r
1285 +               case 8:\r
1286 +                       val = CS8;\r
1287 +                       break;\r
1288 +               case 7:\r
1289 +                       val = CS7;\r
1290 +                       break;\r
1291 +               case 6:\r
1292 +                       val = CS6;\r
1293 +                       break;\r
1294 +               case 5:\r
1295 +                       val = CS5;\r
1296 +                       break;\r
1297 +               default:\r
1298 +                       return 0;\r
1299 +       }\r
1300 +\r
1301 +       *def = val;\r
1302 +       return 1;\r
1303 +}\r
1304 +/* }}} */\r
1305 +\r
1306 +/* {{{ dio_stop_bits_to_define\r
1307 + * Converts a number of stop bits to a termios define\r
1308 + */\r
1309 +static int dio_stop_bits_to_define(int stop_bits, int *def) {\r
1310 +       int val;\r
1311 +\r
1312 +       switch (stop_bits) {\r
1313 +               case 1:\r
1314 +                       val = 0;\r
1315 +                       break;\r
1316 +               case 2:\r
1317 +                       val = CSTOPB;\r
1318 +                       break;\r
1319 +               default:\r
1320 +                       return 0;\r
1321 +       }\r
1322 +\r
1323 +       *def = val;\r
1324 +       return 1;\r
1325 +}\r
1326 +/* }}} */\r
1327 +\r
1328 +/* {{{ dio_parity_to_define\r
1329 + * Converts a parity type to a termios define\r
1330 + */\r
1331 +static int dio_parity_to_define(int parity, int *def) {\r
1332 +       int val;\r
1333 +\r
1334 +       switch (parity) {\r
1335 +               case 0:\r
1336 +                       val = 0;\r
1337 +                       break;\r
1338 +               case 1:\r
1339 +                       val = PARENB | PARODD;\r
1340 +                       break;\r
1341 +               case 2:\r
1342 +                       val = PARENB;\r
1343 +                       break;\r
1344 +               default:\r
1345 +                       return 0;\r
1346 +       }\r
1347 +\r
1348 +       *def = val;\r
1349 +       return 1;\r
1350 +}\r
1351 +/* }}} */\r
1352 +\r
1353 +/* {{{ dio_create_stream_data\r
1354 + * Creates an initialised stream data structure.  Free with efree().\r
1355 + */\r
1356 +php_dio_stream_data * dio_create_stream_data(void) {\r
1357 +       php_dio_posix_stream_data * data = emalloc(sizeof(php_dio_posix_stream_data));\r
1358 +       dio_init_stream_data(&(data->common));\r
1359 +       data->fd = -1;\r
1360 +       data->flags = 0;\r
1361 +\r
1362 +       return (php_dio_stream_data *)data;\r
1363 +}\r
1364 +/* }}} */\r
1365 +\r
1366 +/* {{{ dio_common_write\r
1367 + * Writes count chars from the buffer to the stream described by the stream data.\r
1368 + */\r
1369 +size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {\r
1370 +       size_t ret;\r
1371 +\r
1372 +       /* Blocking writes can be interrupted by signals etc. If\r
1373 +        * interrupted try again. Not sure about non-blocking\r
1374 +        * writes but it doesn't hurt to check. */\r
1375 +       do {\r
1376 +               ret = write(((php_dio_posix_stream_data*)data)->fd, buf, count);\r
1377 +               if (ret > 0) {\r
1378 +                       return ret;\r
1379 +               }\r
1380 +       } while (errno == EINTR);\r
1381 +       return 0;\r
1382 +}\r
1383 +/* }}} */\r
1384 +\r
1385 +#ifdef DIO_NONBLOCK\r
1386 +/* {{{ dio_timeval_subtract\r
1387 + * Calculates the difference between two timevals returning the result in the\r
1388 + * structure pointed to by diffptr.  Returns -1 as error if late time is\r
1389 + * earlier than early time.\r
1390 + */\r
1391 +static int dio_timeval_subtract(struct timeval *late, struct timeval *early, struct timeval *diff) {\r
1392 +       struct timeval *tmp;\r
1393 +\r
1394 +       /* Handle negatives */\r
1395 +       if (late->tv_sec < early->tv_sec) {\r
1396 +               return 0;\r
1397 +       }\r
1398 +\r
1399 +       if ((late->tv_sec == early->tv_sec) && (late->tv_usec < early->tv_usec)) {\r
1400 +               return 0;\r
1401 +       }\r
1402 +\r
1403 +       /* Handle any carry.  If later usec is smaller than earlier usec simple\r
1404 +        * subtraction will result in negative value.  Since usec has a maximum\r
1405 +        * of one second by adding another second before the subtraction the\r
1406 +        * result will always be positive. */\r
1407 +       if (late->tv_usec < early->tv_usec) {\r
1408 +               late->tv_usec  += 1000000;\r
1409 +               late->tv_sec--;\r
1410 +       }\r
1411 +\r
1412 +       /* Once adjusted can just subtract values. */\r
1413 +       diff->tv_sec  = late->tv_sec  - early->tv_sec;\r
1414 +       diff->tv_usec = late->tv_usec - early->tv_usec;\r
1415 +\r
1416 +       return 1;\r
1417 +}\r
1418 +#endif\r
1419 +\r
1420 +/* {{{ dio_common_read\r
1421 + * Reads count chars to the buffer to the stream described by the stream data.\r
1422 + */\r
1423 +size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {\r
1424 +       int fd = ((php_dio_posix_stream_data*)data)->fd;\r
1425 +       size_t ret, total = 0;\r
1426 +       char *ptr = (char*)buf;\r
1427 +\r
1428 +       struct timeval timeout, timeouttmp, before, after, diff;\r
1429 +       fd_set rfds;\r
1430 +\r
1431 +       if (!data->has_timeout) {\r
1432 +               /* Blocking reads can be interrupted by signals etc. If\r
1433 +                * interrupted try again. Not sure about non-blocking\r
1434 +                * reads but it doesn't hurt to check. */\r
1435 +               do {\r
1436 +                       ret = read(fd, (char*)ptr, count);\r
1437 +                       if (ret > 0) {\r
1438 +                               return ret;\r
1439 +                       } else if (!ret) {\r
1440 +                               data->end_of_file = 1;\r
1441 +                       }\r
1442 +               } while ((errno == EINTR) && !data->end_of_file);\r
1443 +               return 0;\r
1444 +       }\r
1445 +#ifdef DIO_NONBLOCK\r
1446 +       else {\r
1447 +               /* Clear timed out flag */\r
1448 +               data->timed_out = 0;\r
1449 +\r
1450 +               /* The initial timeout value */\r
1451 +               timeout.tv_sec  = data->timeout_sec;\r
1452 +               timeout.tv_usec = data->timeout_usec;\r
1453 +\r
1454 +               do {\r
1455 +                       /* The semantics of select() are that you cannot guarantee\r
1456 +                        * that the timeval structure passed in has not been changed by\r
1457 +                        * the select call.  So you keep a copy. */\r
1458 +                       timeouttmp = timeout;\r
1459 +\r
1460 +                       /* The time before we wait for data. */\r
1461 +                       (void) gettimeofday(&before, NULL);\r
1462 +\r
1463 +                       /* Wait for an event on our file descriptor. */\r
1464 +                       FD_ZERO(&rfds);\r
1465 +                       FD_SET(fd, &rfds);\r
1466 +\r
1467 +                       ret = select(fd + 1, &rfds, NULL, NULL, &timeouttmp);\r
1468 +                       /* An error. */\r
1469 +                       if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) {\r
1470 +                               return 0;\r
1471 +                       }\r
1472 +\r
1473 +                       /* We have data to read. */\r
1474 +                       if ((ret > 0) && FD_ISSET(fd, &rfds)) {\r
1475 +                               ret = read(fd, ptr, count);\r
1476 +                               /* Another error */\r
1477 +                               if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) {\r
1478 +                                       return 0;\r
1479 +                               }\r
1480 +\r
1481 +                               if (ret > 0) {\r
1482 +                                       /* Got data, add it to the buffer. */\r
1483 +                                       ptr   += ret;\r
1484 +                                       total += ret;\r
1485 +                                       count -= ret;\r
1486 +                               } else if (!ret) {\r
1487 +                                       /* This should never happen since how can we have\r
1488 +                                        * data to read at an end of file, but still\r
1489 +                                        * just in case! */\r
1490 +                                       data->end_of_file = 1;\r
1491 +                                       break;\r
1492 +                               }\r
1493 +                       }\r
1494 +\r
1495 +                       /* If not timed out and not end of file and not all data read\r
1496 +                        * calculate how long it took us and loop if we still have time\r
1497 +                        * out time left. */\r
1498 +                       if (count) {\r
1499 +                               (void) gettimeofday(&after, NULL);\r
1500 +\r
1501 +                               /* Diff the timevals */\r
1502 +                               (void) dio_timeval_subtract(&after, &before, &diff);\r
1503 +\r
1504 +                               /* Now adjust the timeout. */\r
1505 +                               if (!dio_timeval_subtract(&timeout, &diff, &timeout)) {\r
1506 +                                       /* If it errors we've run out of time. */\r
1507 +                                       data->timed_out = 1;\r
1508 +                                       break;\r
1509 +                               } else if (!timeout.tv_sec && !(timeout.tv_usec / 1000)) {\r
1510 +                                       /* Check for rounding issues (millisecond accuracy) */\r
1511 +                                       data->timed_out = 1;\r
1512 +                                       break;\r
1513 +                               }\r
1514 +                       }\r
1515 +               } while (count); /* Until time out or end of file or all data read. */\r
1516 +\r
1517 +               return total;\r
1518 +       }\r
1519 +#endif\r
1520 +}\r
1521 +/* }}} */\r
1522 +\r
1523 +/* {{{ php_dio_stream_data\r
1524 + * Closes the php_stream.\r
1525 + */\r
1526 +int dio_common_close(php_dio_stream_data *data) {\r
1527 +       if (close(((php_dio_posix_stream_data*)data)->fd) < 0) {\r
1528 +               return 0;\r
1529 +       }\r
1530 +\r
1531 +       return 1;\r
1532 +}\r
1533 +/* }}} */\r
1534 +\r
1535 +/* {{{ dio_common_set_option\r
1536 + * Sets/gets stream options\r
1537 + */\r
1538 +int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {\r
1539 +       int fd = ((php_dio_posix_stream_data*)data)->fd;\r
1540 +       int old_is_blocking;\r
1541 +       int flags;\r
1542 +\r
1543 +       switch (option) {\r
1544 +#ifdef DIO_NONBLOCK\r
1545 +               case PHP_STREAM_OPTION_READ_TIMEOUT:\r
1546 +                       if (ptrparam) {\r
1547 +                               struct timeval *tv = (struct timeval*)ptrparam;\r
1548 +\r
1549 +                               flags = fcntl(fd, F_GETFL, 0);\r
1550 +\r
1551 +                               /* A timeout of zero seconds and zero microseconds disables\r
1552 +                                  any existing timeout. */\r
1553 +                               if (tv->tv_sec || tv->tv_usec) {\r
1554 +                                       data->timeout_sec = tv->tv_sec;\r
1555 +                                       data->timeout_usec = tv->tv_usec;\r
1556 +                                       data->has_timeout = -1;\r
1557 +                                       (void) fcntl(fd, F_SETFL, flags & ~DIO_NONBLOCK);\r
1558 +                               } else {\r
1559 +                                       data->timeout_sec = 0;\r
1560 +                                       data->timeout_usec = 0;\r
1561 +                                       data->has_timeout = 0;\r
1562 +                                       data->timed_out = 0;\r
1563 +                                       (void) fcntl(fd, F_SETFL, flags | DIO_NONBLOCK);\r
1564 +                               }\r
1565 +\r
1566 +                               return PHP_STREAM_OPTION_RETURN_OK;\r
1567 +                       } else {\r
1568 +                               return PHP_STREAM_OPTION_RETURN_ERR;\r
1569 +                       }\r
1570 +\r
1571 +               case PHP_STREAM_OPTION_BLOCKING:\r
1572 +                       flags = fcntl(fd, F_GETFL, 0);\r
1573 +                       if (value) {\r
1574 +                               flags &= ~DIO_NONBLOCK;\r
1575 +                       } else {\r
1576 +                               flags |= DIO_NONBLOCK;\r
1577 +                       }\r
1578 +                       (void) fcntl(fd, F_SETFL, flags);\r
1579 +\r
1580 +                       old_is_blocking = data->is_blocking;\r
1581 +                       data->is_blocking = value;\r
1582 +                       return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;\r
1583 +#endif /* O_NONBLOCK */\r
1584 +\r
1585 +               default:\r
1586 +                       break;\r
1587 +       }\r
1588 +\r
1589 +       return 1;\r
1590 +}\r
1591 +/* }}} */\r
1592 +\r
1593 +/* {{{ dio_raw_open_stream\r
1594 + * Opens the underlying stream.\r
1595 + */\r
1596 +int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {\r
1597 +       php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;\r
1598 +       pdata->flags = dio_stream_mode_to_flags(mode);\r
1599 +\r
1600 +#ifdef DIO_NONBLOCK\r
1601 +       if (!data->is_blocking || data->has_timeout) {\r
1602 +               pdata->flags |= DIO_NONBLOCK;\r
1603 +       }\r
1604 +#endif\r
1605 +\r
1606 +       /* Open the file and handle any errors. */\r
1607 +#ifdef DIO_HAS_FILEPERMS\r
1608 +       if (data->has_perms) {\r
1609 +               pdata->fd = open(filename, pdata->flags, (mode_t)data->perms);\r
1610 +       } else {\r
1611 +               pdata->fd = open(filename, pdata->flags);\r
1612 +       }\r
1613 +#else\r
1614 +       pdata->fd = open(filename, pdata->flags);\r
1615 +#endif\r
1616 +\r
1617 +       if (pdata->fd < 0) {\r
1618 +               switch (errno) {\r
1619 +                       case EEXIST:\r
1620 +                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!");\r
1621 +                               return 0;\r
1622 +                       default:\r
1623 +                               return 0;\r
1624 +               }\r
1625 +       }\r
1626 +\r
1627 +       return 1;\r
1628 +}\r
1629 +/* }}} */\r
1630 +\r
1631 +/* {{{ dio_serial_init\r
1632 + * Initialises the serial settings storing the original settings before hand.\r
1633 + */\r
1634 +static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) {\r
1635 +       php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;\r
1636 +       int ret = 0, data_bits_def, stop_bits_def, parity_def;\r
1637 +       struct termios tio;\r
1638 +       speed_t rate_def;\r
1639 +\r
1640 +       if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {\r
1641 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%ld)", data->data_rate);\r
1642 +               return 0;\r
1643 +       }\r
1644 +\r
1645 +       if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {\r
1646 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits);\r
1647 +               return 0;\r
1648 +       }\r
1649 +\r
1650 +       if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {\r
1651 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);\r
1652 +               return 0;\r
1653 +       }\r
1654 +\r
1655 +       if (!dio_parity_to_define(data->parity, &parity_def)) {\r
1656 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity);\r
1657 +               return 0;\r
1658 +       }\r
1659 +\r
1660 +       ret = tcgetattr(pdata->fd, &(pdata->oldtio));\r
1661 +       if (ret < 0) {\r
1662 +               if ((errno == ENOTTY) || (errno == ENODEV)) {\r
1663 +                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a serial port or terminal!");\r
1664 +               }\r
1665 +               return 0;\r
1666 +       }\r
1667 +\r
1668 +       ret = tcgetattr(pdata->fd, &tio);\r
1669 +       if (ret < 0) {\r
1670 +               return 0;\r
1671 +       }\r
1672 +\r
1673 +       if (data->canonical) {\r
1674 +               tio.c_iflag = IGNPAR | ICRNL;\r
1675 +               tio.c_oflag = 0;\r
1676 +               tio.c_lflag = ICANON;\r
1677 +       } else {\r
1678 +               cfmakeraw(&tio);\r
1679 +       }\r
1680 +\r
1681 +       cfsetispeed(&tio, rate_def);\r
1682 +       cfsetospeed(&tio, rate_def);\r
1683 +\r
1684 +       tio.c_cflag &= ~CSIZE;\r
1685 +       tio.c_cflag |= data_bits_def;\r
1686 +       tio.c_cflag &= ~CSTOPB;\r
1687 +       tio.c_cflag |= stop_bits_def;\r
1688 +       tio.c_cflag &= ~(PARENB|PARODD);\r
1689 +       tio.c_cflag |= parity_def;\r
1690 +\r
1691 +#ifdef CRTSCTS\r
1692 +       tio.c_cflag &= ~(CLOCAL | CRTSCTS);\r
1693 +#else\r
1694 +       tio.c_cflag &= ~CLOCAL;\r
1695 +#endif\r
1696 +       if (!data->flow_control) {\r
1697 +               tio.c_cflag |= CLOCAL;\r
1698 +#ifdef CRTSCTS\r
1699 +       } else {\r
1700 +               tio.c_cflag |= CRTSCTS;\r
1701 +#endif\r
1702 +       }\r
1703 +\r
1704 +       ret = tcsetattr(pdata->fd, TCSANOW, &tio);\r
1705 +       if (ret < 0) {\r
1706 +               return 0;\r
1707 +       }\r
1708 +\r
1709 +       return 1;\r
1710 +}\r
1711 +/* }}} */\r
1712 +\r
1713 +/* {{{ dio_serial_uninit\r
1714 + * Restores the serial settings back to their original state.\r
1715 + */\r
1716 +int dio_serial_uninit(php_dio_stream_data *data) {\r
1717 +       php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;\r
1718 +       int ret;\r
1719 +\r
1720 +       do {\r
1721 +               ret = tcsetattr(pdata->fd, TCSANOW, &(pdata->oldtio));\r
1722 +       } while ((ret < 0) && (errno == EINTR));\r
1723 +\r
1724 +       return 1;\r
1725 +}\r
1726 +/* }}} */\r
1727 +\r
1728 +/* {{{ dio_serial_flush\r
1729 + * Purges the serial buffers of data.\r
1730 + */\r
1731 +int dio_serial_purge(php_dio_stream_data *data) {\r
1732 +       php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;\r
1733 +       int ret;\r
1734 +\r
1735 +       if ((pdata->flags & O_RDWR) == O_RDWR) {\r
1736 +               ret = tcflush(pdata->fd, TCIOFLUSH);\r
1737 +       } else if ((pdata->flags & O_WRONLY) == O_WRONLY) {\r
1738 +               ret = tcflush(pdata->fd, TCOFLUSH);\r
1739 +       } else if ((pdata->flags & O_RDONLY) == O_RDONLY) {\r
1740 +               ret = tcflush(pdata->fd, TCIFLUSH);\r
1741 +       }\r
1742 +\r
1743 +       if (ret < 0) {\r
1744 +               return 0;\r
1745 +       }\r
1746 +\r
1747 +       return 1;\r
1748 +}\r
1749 +/* }}} */\r
1750 +\r
1751 +/* {{{ dio_serial_open_stream\r
1752 + * Opens the underlying stream.\r
1753 + */\r
1754 +int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {\r
1755 +       php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;\r
1756 +\r
1757 +#ifdef O_NOCTTY\r
1758 +       /* We don't want a controlling TTY */\r
1759 +       pdata->flags |= O_NOCTTY;\r
1760 +#endif\r
1761 +\r
1762 +       if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {\r
1763 +               return 0;\r
1764 +       }\r
1765 +\r
1766 +       if (!dio_serial_init(data TSRMLS_CC)) {\r
1767 +               close(pdata->fd);\r
1768 +               return 0;\r
1769 +       }\r
1770 +\r
1771 +       return 1;\r
1772 +}\r
1773 +/* }}} */\r
1774 +\r
1775 +/*\r
1776 + * Local variables:\r
1777 + * c-basic-offset: 4\r
1778 + * tab-width: 4\r
1779 + * End:\r
1780 + * vim600: fdm=marker\r
1781 + * vim: sw=4 ts=4 noet\r
1782 + */\r
1783 --- /dev/null
1784 +++ b/ext/dio/dio_stream_wrappers.c
1785 @@ -0,0 +1,406 @@
1786 +/*
1787 +   +----------------------------------------------------------------------+
1788 +   | PHP Version 5                                                        |
1789 +   +----------------------------------------------------------------------+
1790 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |
1791 +   +----------------------------------------------------------------------+
1792 +   | This source file is subject to version 3.0 of the PHP license,       |
1793 +   | that is bundled with this package in the file LICENSE, and is        |
1794 +   | available through the world-wide-web at the following url:           |
1795 +   | http://www.php.net/license/3_0.txt.                                  |
1796 +   | If you did not receive a copy of the PHP license and are unable to   |
1797 +   | obtain it through the world-wide-web, please send a note to          |
1798 +   | license@php.net so we can mail you a copy immediately.               |
1799 +   +----------------------------------------------------------------------+
1800 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |
1801 +   +----------------------------------------------------------------------+
1802 + */
1803 +
1804 +#ifdef HAVE_CONFIG_H
1805 +#include "config.h"
1806 +#endif
1807 +
1808 +#include "php.h"
1809 +#include "ext/standard/url.h"
1810 +
1811 +#include "php_dio.h"
1812 +#include "php_dio_common.h"
1813 +#include "php_dio_stream_wrappers.h"
1814 +
1815 +/*
1816 +   +----------------------------------------------------------------------+
1817 +   | Raw stream handling                                                  |
1818 +   +----------------------------------------------------------------------+
1819 +*/
1820 +
1821 +/* {{{ dio_stream_write
1822 + * Write to the stream
1823 + */
1824 +static size_t dio_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
1825 +{
1826 +       return dio_common_write((php_dio_stream_data*)stream->abstract, buf, count);
1827 +}
1828 +/* }}} */
1829 +
1830 +/* {{{ dio_stream_read
1831 + * Read from the stream
1832 + */
1833 +static size_t dio_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
1834 +{
1835 +       php_dio_stream_data* data = (php_dio_stream_data*)stream->abstract;
1836 +       size_t bytes = dio_common_read(data, buf, count);
1837 +       stream->eof = data->end_of_file;
1838 +
1839 +       return bytes;
1840 +}
1841 +/* }}} */
1842 +
1843 +/* {{{ dio_stream_flush
1844 + * Flush the stream.  For raw streams this does nothing.
1845 + */
1846 +static int dio_stream_flush(php_stream *stream TSRMLS_DC)
1847 +{
1848 +       return 1;
1849 +}
1850 +/* }}} */
1851 +
1852 +/* {{{ dio_stream_close
1853 + * Close the stream
1854 + */
1855 +static int dio_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
1856 +{
1857 +       php_dio_stream_data *abstract = (php_dio_stream_data*)stream->abstract;
1858 +
1859 +       if (!dio_common_close(abstract)) {
1860 +               return 0;
1861 +       }
1862 +
1863 +       efree(abstract);
1864 +       return 1;
1865 +}
1866 +/* }}} */
1867 +
1868 +/* {{{ dio_stream_set_option
1869 + * Set the stream options.
1870 + */
1871 +static int dio_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
1872 +{
1873 +       php_dio_stream_data *abstract = (php_dio_stream_data*)stream->abstract;
1874 +
1875 +       switch (option) {
1876 +               case PHP_STREAM_OPTION_META_DATA_API:
1877 +#ifdef DIO_NONBLOCK
1878 +                       add_assoc_bool((zval *)ptrparam, "timed_out", abstract->timed_out);
1879 +                       add_assoc_bool((zval *)ptrparam, "blocked", abstract->is_blocking);
1880 +#endif
1881 +                       add_assoc_bool((zval *)ptrparam, "eof", stream->eof);
1882 +                       return PHP_STREAM_OPTION_RETURN_OK;
1883 +
1884 +#if PHP_MAJOR_VERSION >= 5
1885 +               case PHP_STREAM_OPTION_CHECK_LIVENESS:
1886 +                       stream->eof = abstract->end_of_file;
1887 +                       return PHP_STREAM_OPTION_RETURN_OK;
1888 +#endif /* PHP_MAJOR_VERSION >= 5 */
1889 +
1890 +               default:
1891 +                       break;
1892 +       }
1893 +
1894 +       return dio_common_set_option(abstract, option, value, ptrparam);
1895 +}
1896 +/* }}} */
1897 +
1898 +php_stream_ops dio_raw_stream_ops = {
1899 +       dio_stream_write,
1900 +       dio_stream_read,
1901 +       dio_stream_close,
1902 +       dio_stream_flush,
1903 +       "dio",
1904 +       NULL, /* seek */
1905 +       NULL, /* cast */
1906 +       NULL, /* stat */
1907 +       dio_stream_set_option,
1908 +};
1909 +
1910 +/* {{{ dio_raw_fopen_wrapper
1911 + * fopen for the dio.raw stream.
1912 + */
1913 +static php_stream *dio_raw_fopen_wrapper(php_stream_wrapper *wrapper,
1914 +                                         char *path, char *mode,
1915 +                                         int options, char **opened_path,
1916 +                                         php_stream_context *context STREAMS_DC TSRMLS_DC) {
1917 +       php_dio_stream_data *data;
1918 +       php_stream *stream;
1919 +       char *filename;
1920 +
1921 +       /* Check it was actually for us (not a corrupted function pointer
1922 +          somewhere!). */
1923 +       if (strncmp(path, DIO_RAW_STREAM_PROTOCOL, sizeof(DIO_RAW_STREAM_PROTOCOL) - 1)) {
1924 +               return NULL;
1925 +       }
1926 +
1927 +       /* Get the actually file system name/path. */
1928 +       filename = path + sizeof(DIO_RAW_STREAM_PROTOCOL) - 1;
1929 +
1930 +       /* Check we can actually access it. */
1931 +       if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) {
1932 +               return NULL;
1933 +       }
1934 +
1935 +       data = dio_create_stream_data();
1936 +       data->stream_type = DIO_STREAM_TYPE_RAW;
1937 +
1938 +       /* Parse the context. */
1939 +       if (context) {
1940 +               dio_stream_context_get_basic_options(context, data TSRMLS_CC);
1941 +       }
1942 +
1943 +       /* Try and open a raw stream. */
1944 +       if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {
1945 +               return NULL;
1946 +       }
1947 +
1948 +       /* Create a PHP stream based on raw stream */
1949 +       stream = php_stream_alloc(&dio_raw_stream_ops, data, 0, mode);
1950 +       if (!stream) {
1951 +               (void) dio_common_close(data);
1952 +               efree(data);
1953 +       }
1954 +
1955 +       return stream;
1956 +}
1957 +/* }}} */
1958 +
1959 +static php_stream_wrapper_ops dio_raw_stream_wops = {
1960 +       dio_raw_fopen_wrapper,
1961 +       NULL, /* stream_close */
1962 +       NULL, /* stat */
1963 +       NULL, /* stat_url */
1964 +       NULL, /* opendir */
1965 +       DIO_RAW_STREAM_NAME
1966 +};
1967 +
1968 +php_stream_wrapper php_dio_raw_stream_wrapper = {
1969 +       &dio_raw_stream_wops,
1970 +       NULL,
1971 +       0
1972 +};
1973 +
1974 +/* {{{ proto dio_raw(string filename, string mode[, array options])
1975 + * Opens a raw direct IO stream.
1976 + */
1977 +PHP_FUNCTION(dio_raw) {
1978 +       zval *options = NULL;
1979 +       php_dio_stream_data *data;
1980 +       php_stream *stream;
1981 +
1982 +       char *filename;
1983 +       int   filename_len;
1984 +       char *mode;
1985 +       int   mode_len;
1986 +
1987 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &filename, &filename_len, &mode, &mode_len, &options) == FAILURE) {
1988 +               RETURN_FALSE;
1989 +       }
1990 +
1991 +       /* Check the third argument is an array. */
1992 +       if (options && (Z_TYPE_P(options) != IS_ARRAY)) {
1993 +               RETURN_FALSE;
1994 +       }
1995 +
1996 +       /* Check we can actually access the file. */
1997 +       if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) {
1998 +               RETURN_FALSE;
1999 +       }
2000 +
2001 +       data = dio_create_stream_data();
2002 +       data->stream_type = DIO_STREAM_TYPE_RAW;
2003 +
2004 +       if (options) {
2005 +               dio_assoc_array_get_basic_options(options, data TSRMLS_CC);
2006 +       }
2007 +
2008 +       /* Try and open a raw stream. */
2009 +       if (dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {
2010 +               stream = php_stream_alloc(&dio_raw_stream_ops, data, 0, mode);
2011 +               if (!stream) {
2012 +                       (void) dio_common_close(data);
2013 +                       efree(data);
2014 +                       RETURN_FALSE;
2015 +               }
2016 +       }
2017 +
2018 +       php_stream_to_zval(stream, return_value);
2019 +}
2020 +/* }}} */
2021 +
2022 +/*
2023 +   +----------------------------------------------------------------------+
2024 +   | Serial stream handling                                               |
2025 +   +----------------------------------------------------------------------+
2026 +*/
2027 +
2028 +/* {{{ dio_stream_flush
2029 + * Flush the stream.  If the stream is read only, it flushes the read
2030 + * stream, if it is write only it flushes the write, otherwise it flushes
2031 + * both.
2032 + */
2033 +static int dio_serial_stream_flush(php_stream *stream TSRMLS_DC)
2034 +{
2035 +       return dio_serial_purge((php_dio_stream_data*)stream->abstract);
2036 +}
2037 +/* }}} */
2038 +
2039 +/* {{{ dio_stream_close
2040 + * Close the stream.  Restores the serial settings to their value before
2041 + * the stream was open.
2042 + */
2043 +static int dio_serial_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
2044 +{
2045 +       php_dio_stream_data *abstract = (php_dio_stream_data*)stream->abstract;
2046 +
2047 +       if (!dio_serial_uninit(abstract)) {
2048 +               return 0;
2049 +       }
2050 +
2051 +       if (!dio_common_close(abstract)) {
2052 +               return 0;
2053 +       }
2054 +
2055 +       efree(abstract);
2056 +       return 1;
2057 +}
2058 +/* }}} */
2059 +
2060 +php_stream_ops dio_serial_stream_ops = {
2061 +       dio_stream_write,
2062 +       dio_stream_read,
2063 +       dio_serial_stream_close,
2064 +       dio_serial_stream_flush,
2065 +       "dio",
2066 +       NULL, /* seek */
2067 +       NULL, /* cast */
2068 +       NULL, /* stat */
2069 +       dio_stream_set_option,
2070 +};
2071 +
2072 +/* {{{ dio_raw_fopen_wrapper
2073 + * fopen for the dio.raw stream.
2074 + */
2075 +static php_stream *dio_serial_fopen_wrapper(php_stream_wrapper *wrapper,
2076 +                                         char *path, char *mode,
2077 +                                         int options, char **opened_path,
2078 +                                         php_stream_context *context STREAMS_DC TSRMLS_DC) {
2079 +       php_dio_stream_data *data;
2080 +       php_stream *stream;
2081 +       char *filename;
2082 +
2083 +       /* Check it was actually for us (not a corrupted function pointer
2084 +          somewhere!). */
2085 +       if (strncmp(path, DIO_SERIAL_STREAM_PROTOCOL, sizeof(DIO_SERIAL_STREAM_PROTOCOL) - 1)) {
2086 +               return NULL;
2087 +       }
2088 +
2089 +       /* Get the actually file system name/path. */
2090 +       filename = path + sizeof(DIO_SERIAL_STREAM_PROTOCOL) - 1;
2091 +
2092 +       /* Check we can actually access it. */
2093 +       if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) {
2094 +               return NULL;
2095 +       }
2096 +
2097 +       data = dio_create_stream_data();
2098 +       data->stream_type = DIO_STREAM_TYPE_SERIAL;
2099 +
2100 +       /* Parse the context. */
2101 +       if (context) {
2102 +               dio_stream_context_get_basic_options(context, data TSRMLS_CC);
2103 +               dio_stream_context_get_serial_options(context, data TSRMLS_CC);
2104 +       }
2105 +
2106 +       /* Try and open a serial stream. */
2107 +       if (!dio_serial_open_stream(filename, mode, data TSRMLS_CC)) {
2108 +               return NULL;
2109 +       }
2110 +
2111 +       stream = php_stream_alloc(&dio_serial_stream_ops, data, 0, mode);
2112 +       if (!stream) {
2113 +               efree(data);
2114 +       }
2115 +
2116 +       return stream;
2117 +}
2118 +/* }}} */
2119 +
2120 +static php_stream_wrapper_ops dio_serial_stream_wops = {
2121 +       dio_serial_fopen_wrapper,
2122 +       NULL, /* stream_close */
2123 +       NULL, /* stat */
2124 +       NULL, /* stat_url */
2125 +       NULL, /* opendir */
2126 +       DIO_SERIAL_STREAM_NAME
2127 +};
2128 +
2129 +php_stream_wrapper php_dio_serial_stream_wrapper = {
2130 +       &dio_serial_stream_wops,
2131 +       NULL,
2132 +       0
2133 +};
2134 +
2135 +/* {{{ proto dio_serial(string filename, string mode[, array options])
2136 + * Opens a serial direct IO stream.
2137 + */
2138 +PHP_FUNCTION(dio_serial) {
2139 +       zval *options = NULL;
2140 +       php_dio_stream_data *data;
2141 +       php_stream *stream;
2142 +
2143 +       char *filename;
2144 +       int   filename_len;
2145 +       char *mode;
2146 +       int   mode_len;
2147 +
2148 +       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &filename, &filename_len, &mode, &mode_len, &options) == FAILURE) {
2149 +               RETURN_FALSE;
2150 +       }
2151 +
2152 +       /* Check the third argument is an array. */
2153 +       if (options && (Z_TYPE_P(options) != IS_ARRAY)) {
2154 +               php_error_docref(NULL TSRMLS_CC, E_WARNING,"dio_serial, the third argument should be an array of options");
2155 +               RETURN_FALSE;
2156 +       }
2157 +
2158 +       /* Check we can actually access the file. */
2159 +       if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) {
2160 +               RETURN_FALSE;
2161 +       }
2162 +
2163 +       data = dio_create_stream_data();
2164 +       data->stream_type = DIO_STREAM_TYPE_SERIAL;
2165 +
2166 +       if (options) {
2167 +               dio_assoc_array_get_basic_options(options, data TSRMLS_CC);
2168 +               dio_assoc_array_get_serial_options(options, data TSRMLS_CC);
2169 +       }
2170 +
2171 +       /* Try and open a serial stream. */
2172 +       if (dio_serial_open_stream(filename, mode, data TSRMLS_CC)) {
2173 +               stream = php_stream_alloc(&dio_serial_stream_ops, data, 0, mode);
2174 +               if (!stream) {
2175 +                       efree(data);
2176 +                       RETURN_FALSE;
2177 +               }
2178 +       }
2179 +
2180 +       php_stream_to_zval(stream, return_value);
2181 +}
2182 +/* }}} */
2183 +
2184 +/*
2185 + * Local variables:
2186 + * c-basic-offset: 4
2187 + * tab-width: 4
2188 + * End:
2189 + * vim600: fdm=marker
2190 + * vim: sw=4 ts=4 noet
2191 + */
2192 --- /dev/null
2193 +++ b/ext/dio/dio_win32.c
2194 @@ -0,0 +1,669 @@
2195 +/*\r
2196 +   +----------------------------------------------------------------------+\r
2197 +   | PHP Version 5                                                        |\r
2198 +   +----------------------------------------------------------------------+\r
2199 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |\r
2200 +   +----------------------------------------------------------------------+\r
2201 +   | This source file is subject to version 3.0 of the PHP license,       |\r
2202 +   | that is bundled with this package in the file LICENSE, and is        |\r
2203 +   | available through the world-wide-web at the following url:           |\r
2204 +   | http://www.php.net/license/3_0.txt.                                  |\r
2205 +   | If you did not receive a copy of the PHP license and are unable to   |\r
2206 +   | obtain it through the world-wide-web, please send a note to          |\r
2207 +   | license@php.net so we can mail you a copy immediately.               |\r
2208 +   +----------------------------------------------------------------------+\r
2209 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |\r
2210 +   +----------------------------------------------------------------------+\r
2211 + */\r
2212 +\r
2213 +#ifdef HAVE_CONFIG_H\r
2214 +#include "config.h"\r
2215 +#endif\r
2216 +\r
2217 +#include "php.h"\r
2218 +\r
2219 +#include "php_dio_common.h"\r
2220 +\r
2221 +/* {{{ dio_data_rate_to_define\r
2222 + * Converts a numeric data rate to a termios define\r
2223 + */\r
2224 +static int dio_data_rate_to_define(long rate, DWORD *def) {\r
2225 +       switch (rate) {\r
2226 +               case 75:\r
2227 +               case 110:\r
2228 +               case 134:\r
2229 +               case 150:\r
2230 +               case 300:\r
2231 +               case 600:\r
2232 +               case 1200:\r
2233 +               case 1800:\r
2234 +               case 2400:\r
2235 +               case 4800:\r
2236 +               case 7200:\r
2237 +               case 9600:\r
2238 +               case 14400:\r
2239 +               case 19200:\r
2240 +               case 38400:\r
2241 +               case 57600:\r
2242 +               case 115200:\r
2243 +               case 56000:\r
2244 +               case 128000:\r
2245 +                       break;\r
2246 +               default:\r
2247 +                       return 0;\r
2248 +       }\r
2249 +\r
2250 +       *def = (DWORD)rate;\r
2251 +       return 1;\r
2252 +}\r
2253 +/* }}} */\r
2254 +\r
2255 +\r
2256 +/* {{{ dio_data_bits_to_define\r
2257 + * Converts a number of data bits to a termios define\r
2258 + */\r
2259 +static int dio_data_bits_to_define(int data_bits, DWORD *def) {\r
2260 +       switch (data_bits) {\r
2261 +               case 8:\r
2262 +               case 7:\r
2263 +               case 6:\r
2264 +               case 5:\r
2265 +               case 4:\r
2266 +                       break;\r
2267 +               default:\r
2268 +                       return 0;\r
2269 +       }\r
2270 +\r
2271 +       *def = (DWORD)data_bits;\r
2272 +       return 1;\r
2273 +}\r
2274 +/* }}} */\r
2275 +\r
2276 +/* {{{ dio_stop_bits_to_define\r
2277 + * Converts a number of stop bits to a termios define\r
2278 + */\r
2279 +static int dio_stop_bits_to_define(int stop_bits, DWORD *def) {\r
2280 +       DWORD val;\r
2281 +\r
2282 +       switch (stop_bits) {\r
2283 +               case 1:\r
2284 +                       val = 0;\r
2285 +                       break;\r
2286 +               case 2:\r
2287 +                       val = 2;\r
2288 +                       break;\r
2289 +               case 3:\r
2290 +                       val = 1;\r
2291 +                       break;\r
2292 +               default:\r
2293 +                       return 0;\r
2294 +       }\r
2295 +\r
2296 +       *def = val;\r
2297 +       return 1;\r
2298 +}\r
2299 +/* }}} */\r
2300 +\r
2301 +/* {{{ dio_parity_to_define\r
2302 + * Converts a parity type to a termios define\r
2303 + */\r
2304 +static int dio_parity_to_define(int parity, DWORD *def) {\r
2305 +       switch (parity) {\r
2306 +               case 0:\r
2307 +               case 1:\r
2308 +               case 2:\r
2309 +                       break;\r
2310 +               default:\r
2311 +                       return 0;\r
2312 +       }\r
2313 +\r
2314 +       *def = (DWORD)parity;\r
2315 +       return 1;\r
2316 +}\r
2317 +/* }}} */\r
2318 +\r
2319 +/* {{{ dio_create_stream_data\r
2320 + * Creates an initialised stream data structure.  Free with efree().\r
2321 + */\r
2322 +php_dio_stream_data * dio_create_stream_data(void) {\r
2323 +       php_dio_win32_stream_data * data = emalloc(sizeof(php_dio_win32_stream_data));\r
2324 +       memset(data, 0, sizeof(php_dio_win32_stream_data));\r
2325 +       dio_init_stream_data(&(data->common));\r
2326 +       data->handle = INVALID_HANDLE_VALUE;\r
2327 +       data->desired_access = 0;\r
2328 +       data->creation_disposition = 0;\r
2329 +       data->olddcb.DCBlength = sizeof(DCB);\r
2330 +\r
2331 +       return (php_dio_stream_data *)data;\r
2332 +}\r
2333 +/* }}} */\r
2334 +\r
2335 +/* {{{ dio_common_write\r
2336 + * Writes count chars from the buffer to the stream described by the stream data.\r
2337 + */\r
2338 +size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {\r
2339 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2340 +       DWORD total = 0;\r
2341 +\r
2342 +       if (WriteFile(wdata->handle, buf, (DWORD)count, &total, NULL)) {\r
2343 +               return (size_t)total;\r
2344 +       }\r
2345 +\r
2346 +       return 0;\r
2347 +}\r
2348 +/* }}} */\r
2349 +\r
2350 +/* {{{ dio_buffer_read\r
2351 + * Reads any available chars from the canonical buffer.\r
2352 + */\r
2353 +static size_t dio_buffer_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {\r
2354 +       php_dio_win32_canon_data *canon_data = wdata->canon_data;\r
2355 +       size_t total = 0;\r
2356 +\r
2357 +       /* Read always follows write.  I.e. if read ptr > write ptr buffer has\r
2358 +          wrapped and so we need to copy two blocks of data. */\r
2359 +       if (canon_data->read_pos > canon_data->write_pos) {\r
2360 +\r
2361 +               /* Check we actually need to copy both blocks */\r
2362 +               if ((canon_data->size - canon_data->read_pos) > count) {\r
2363 +\r
2364 +                       /* No we don't.  Just copy as much as we were asked for. */\r
2365 +                       memcpy((char*)buf, \r
2366 +                                  &(canon_data->buf[canon_data->read_pos]), \r
2367 +                                  count);\r
2368 +                       /* Update the read pointer. */\r
2369 +                       canon_data->read_pos += count;\r
2370 +\r
2371 +                       /* Return the amount read. */\r
2372 +                       return count;\r
2373 +               } else {\r
2374 +\r
2375 +                       /* We need to copy both blocks so copy data up to the end of \r
2376 +                          the buffer. */\r
2377 +                       total = canon_data->size - canon_data->read_pos;\r
2378 +                       memcpy((char*)buf, \r
2379 +                                  &(canon_data->buf[canon_data->read_pos]), \r
2380 +                                  total);\r
2381 +                       canon_data->read_pos = 0;\r
2382 +                       count -= total;\r
2383 +\r
2384 +                       /* Now copy the data from the start of the buffer either up\r
2385 +                          count or the number of bytes in the buffer. */\r
2386 +\r
2387 +                       if (canon_data->write_pos > count) {\r
2388 +                               memcpy((char*)buf, canon_data->buf, count);\r
2389 +                               canon_data->read_pos = count;\r
2390 +                               total += count;\r
2391 +\r
2392 +                               return total;\r
2393 +                       } else {\r
2394 +                               memcpy((char*)buf, canon_data->buf, canon_data->write_pos);\r
2395 +                               canon_data->read_pos = canon_data->write_pos;\r
2396 +                               total += canon_data->write_pos;\r
2397 +\r
2398 +                               return total;\r
2399 +                       }\r
2400 +               }\r
2401 +\r
2402 +       /* Else if write follows read.  This is a simpler case.  We just copy \r
2403 +          either all the data buffered or count, which ever is smaller. */\r
2404 +       } else if (canon_data->write_pos > canon_data->read_pos) {\r
2405 +               if ((canon_data->write_pos - canon_data->read_pos) > count) {\r
2406 +                       memcpy((char*)buf, \r
2407 +                                  &(canon_data->buf[canon_data->read_pos]), \r
2408 +                                  count);\r
2409 +                       canon_data->read_pos += count;\r
2410 +\r
2411 +                       return count;\r
2412 +               } else {\r
2413 +                       total = canon_data->write_pos - canon_data->read_pos;\r
2414 +                       memcpy((char*)buf, \r
2415 +                                  &(canon_data->buf[canon_data->read_pos]), \r
2416 +                                  total);\r
2417 +                       canon_data->read_pos += total;\r
2418 +\r
2419 +                       return total;\r
2420 +               }\r
2421 +       }\r
2422 +\r
2423 +       /* Else we need to read more data from the data port. */\r
2424 +       return 0;\r
2425 +}\r
2426 +\r
2427 +/* {{{ dio_com_read\r
2428 + * Read chars from the data port.\r
2429 + */\r
2430 +static size_t dio_com_read(php_dio_stream_data *data, const char *buf, size_t count) {\r
2431 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2432 +       DWORD err, total = 0;\r
2433 +\r
2434 +       if (ReadFile(wdata->handle, (void*)buf, (DWORD)count, &total, NULL)) {\r
2435 +\r
2436 +               if (total) {\r
2437 +                       return (size_t)total;\r
2438 +               }\r
2439 +\r
2440 +               data->end_of_file = 1;\r
2441 +       }\r
2442 +\r
2443 +       if (!data->end_of_file) {\r
2444 +               err = GetLastError();\r
2445 +\r
2446 +               if (ERROR_HANDLE_EOF == err) {\r
2447 +                       data->end_of_file = 1;\r
2448 +               }\r
2449 +       }\r
2450 +\r
2451 +       return 0;\r
2452 +}\r
2453 +\r
2454 +/* {{{ dio_canonical_read\r
2455 + * Reads chars from the input stream until the internal buffer is full or a new\r
2456 + * line is reached.\r
2457 + */\r
2458 +static size_t dio_canonical_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {\r
2459 +       php_dio_win32_canon_data *canon_data = wdata->canon_data;\r
2460 +       size_t total = 0;\r
2461 +       char ch;\r
2462 +\r
2463 +       /* See if there's any buffered data and copy it. */\r
2464 +       total = dio_buffer_read(wdata, buf, count);\r
2465 +       if (total) {\r
2466 +               return total;\r
2467 +       }\r
2468 +\r
2469 +       /* Need to read more data from the data port.  Buffer should be empty(er)\r
2470 +          by now. */\r
2471 +       do {\r
2472 +               /* Is the buffer full? */\r
2473 +               if (((canon_data->write_pos + 1) % canon_data->size) == \r
2474 +                       canon_data->read_pos) {\r
2475 +                       break;\r
2476 +               }\r
2477 +\r
2478 +               /* Read a byte from the input checking for EOF. */\r
2479 +               if (!dio_com_read((php_dio_stream_data*)wdata, &ch, 1)) {\r
2480 +                       break;\r
2481 +               }\r
2482 +\r
2483 +               /* Translate CR to newlines (same as ICRNL in POSIX) */\r
2484 +               ch = (ch != '\r') ? ch : '\n';\r
2485 +\r
2486 +               /* We read a character!  So buffer it. */\r
2487 +               canon_data->buf[canon_data->write_pos++] = ch;\r
2488 +               if (canon_data->write_pos >= canon_data->size) {\r
2489 +                       canon_data->write_pos = 0;\r
2490 +               }\r
2491 +\r
2492 +               /* End of line/input (^D)? */\r
2493 +       } while ((ch != '\n') && (ch != 0x04));\r
2494 +\r
2495 +       return dio_buffer_read(wdata, buf, count);\r
2496 +}\r
2497 +/* }}} */\r
2498 +\r
2499 +/* {{{ dio_common_read\r
2500 + * Reads count chars to the buffer to the stream described by the stream data.\r
2501 + */\r
2502 +size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {\r
2503 +\r
2504 +       /* You ask for no bytes you'll get none :-) */\r
2505 +       if (!count) {\r
2506 +               return 0;\r
2507 +       }\r
2508 +\r
2509 +       if (data->canonical) {\r
2510 +               return dio_canonical_read((php_dio_win32_stream_data*)data, buf, count);\r
2511 +       } else {\r
2512 +               return dio_com_read(data, buf, count);\r
2513 +       }\r
2514 +}\r
2515 +/* }}} */\r
2516 +\r
2517 +/* {{{ php_dio_stream_data\r
2518 + * Closes the php_stream.\r
2519 + */\r
2520 +int dio_common_close(php_dio_stream_data *data) {\r
2521 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2522 +\r
2523 +       if (data->canonical) {\r
2524 +               efree(wdata->canon_data);\r
2525 +       }\r
2526 +\r
2527 +       if (!CloseHandle(wdata->handle)) {\r
2528 +               return 0;\r
2529 +       }\r
2530 +\r
2531 +       return 1;\r
2532 +}\r
2533 +/* }}} */\r
2534 +\r
2535 +/* {{{ dio_common_set_option\r
2536 + * Sets/gets stream options\r
2537 + */\r
2538 +int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {\r
2539 +       COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };\r
2540 +       int old_is_blocking = 0;\r
2541 +\r
2542 +       /* Can't do timeouts or non blocking with raw windows streams :-( */\r
2543 +       if (DIO_STREAM_TYPE_SERIAL == data->stream_type) {\r
2544 +               switch (option) {\r
2545 +                       case PHP_STREAM_OPTION_BLOCKING:\r
2546 +                               old_is_blocking   = data->is_blocking;\r
2547 +                               data->is_blocking = value ? 1 : 0;\r
2548 +\r
2549 +                               /* Only change values if we need to change them. */\r
2550 +                               if (data->is_blocking != old_is_blocking) {\r
2551 +                                       /* If we're not blocking but don't have a timeout\r
2552 +                                          set to return immediately */\r
2553 +                                       if (!data->is_blocking && !data->has_timeout) {\r
2554 +                                               cto.ReadIntervalTimeout = MAXDWORD;\r
2555 +                                       }\r
2556 +\r
2557 +                                       /* If we have a timeout ignore the blocking and set\r
2558 +                                          the total time in which to read the data */\r
2559 +                                       if (data->has_timeout) {\r
2560 +                                               cto.ReadIntervalTimeout = MAXDWORD;\r
2561 +                                               cto.ReadTotalTimeoutMultiplier  = MAXDWORD;\r
2562 +                                               cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +\r
2563 +                                                       (data->timeout_sec * 1000);\r
2564 +                                       }\r
2565 +\r
2566 +                                       if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {\r
2567 +                                               return PHP_STREAM_OPTION_RETURN_ERR;\r
2568 +                                       }\r
2569 +                               }\r
2570 +                               return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;\r
2571 +\r
2572 +                       case PHP_STREAM_OPTION_READ_TIMEOUT:\r
2573 +                               if (ptrparam) {\r
2574 +                                       /* struct timeval is supported with PHP_WIN32 defined. */\r
2575 +                                       struct timeval *tv = (struct timeval*)ptrparam;\r
2576 +\r
2577 +                                       /* A timeout of zero seconds and zero microseconds disables\r
2578 +                                          any existing timeout. */\r
2579 +                                       if (tv->tv_sec || tv->tv_usec) {\r
2580 +                                               data->timeout_sec = tv->tv_sec;\r
2581 +                                               data->timeout_usec = tv->tv_usec;\r
2582 +                                               data->has_timeout = -1;\r
2583 +\r
2584 +                                               cto.ReadIntervalTimeout = MAXDWORD;\r
2585 +                                               cto.ReadTotalTimeoutMultiplier  = MAXDWORD;\r
2586 +                                               cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +\r
2587 +                                                       (data->timeout_sec * 1000);\r
2588 +                                       } else {\r
2589 +                                               data->timeout_sec = 0;\r
2590 +                                               data->timeout_usec = 0;\r
2591 +                                               data->has_timeout = 0;\r
2592 +                                               data->timed_out = 0;\r
2593 +\r
2594 +                                               /* If we're not blocking but don't have a timeout\r
2595 +                                                  set to return immediately */\r
2596 +                                               if (!data->is_blocking) {\r
2597 +                                                       cto.ReadIntervalTimeout = MAXDWORD;\r
2598 +                                               }\r
2599 +                                       }\r
2600 +\r
2601 +                                       if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {\r
2602 +                                               return PHP_STREAM_OPTION_RETURN_ERR;\r
2603 +                                       } else {\r
2604 +                                               return PHP_STREAM_OPTION_RETURN_OK;\r
2605 +                                       }\r
2606 +                               } else {\r
2607 +                                       return PHP_STREAM_OPTION_RETURN_ERR;\r
2608 +                               }\r
2609 +\r
2610 +                       default:\r
2611 +                               break;\r
2612 +               }\r
2613 +       }\r
2614 +\r
2615 +       return 1;\r
2616 +}\r
2617 +/* }}} */\r
2618 +\r
2619 +/* {{{ dio_raw_open_stream\r
2620 + * Opens the underlying stream.\r
2621 + */\r
2622 +int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {\r
2623 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2624 +       DWORD err;\r
2625 +\r
2626 +       switch(*mode) {\r
2627 +               case 'r':\r
2628 +                       wdata->creation_disposition = OPEN_EXISTING;\r
2629 +                       break;\r
2630 +               case 'w':\r
2631 +                       wdata->creation_disposition = TRUNCATE_EXISTING;\r
2632 +                       break;\r
2633 +               case 'a':\r
2634 +                       wdata->creation_disposition = OPEN_ALWAYS;\r
2635 +                       break;\r
2636 +               case 'x':\r
2637 +                       wdata->creation_disposition = CREATE_NEW;\r
2638 +                       break;\r
2639 +       }\r
2640 +       mode ++;\r
2641 +\r
2642 +       if (*mode && (*mode != '+')) {\r
2643 +               mode++;\r
2644 +       }\r
2645 +\r
2646 +       if (*mode && (*mode == '+')) {\r
2647 +               wdata->desired_access = GENERIC_READ | GENERIC_WRITE;\r
2648 +       } else if (OPEN_EXISTING == wdata->creation_disposition) {\r
2649 +               wdata->desired_access = GENERIC_READ;\r
2650 +       } else {\r
2651 +               wdata->desired_access = GENERIC_WRITE;\r
2652 +       }\r
2653 +\r
2654 +       wdata->handle = CreateFile(filename, wdata->desired_access, 0,\r
2655 +                       NULL, wdata->creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);\r
2656 +       if (INVALID_HANDLE_VALUE == wdata->handle) {\r
2657 +               err = GetLastError();\r
2658 +               switch (err) {\r
2659 +                       case ERROR_FILE_EXISTS:\r
2660 +                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!");\r
2661 +                               return 0;\r
2662 +\r
2663 +                       case ERROR_FILE_NOT_FOUND:\r
2664 +                               /* ERROR_FILE_NOT_FOUND with TRUNCATE_EXISTING means that\r
2665 +                                * the file doesn't exist so now try to create it. */\r
2666 +                               if (TRUNCATE_EXISTING == wdata->creation_disposition) {\r
2667 +                                       wdata->handle = CreateFile(filename, wdata->desired_access, 0,\r
2668 +                                                               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\r
2669 +                                       if (INVALID_HANDLE_VALUE == wdata->handle) {\r
2670 +                                               err = GetLastError();\r
2671 +                                               return 0;\r
2672 +                                       }\r
2673 +                               } else {\r
2674 +                                       return 0;\r
2675 +                               }\r
2676 +                               break;\r
2677 +\r
2678 +                       default:\r
2679 +                               return 0;\r
2680 +               }\r
2681 +       }\r
2682 +\r
2683 +       /* If canonical allocate the canonical buffer. */\r
2684 +       if (data->canonical) {\r
2685 +               wdata->canon_data = emalloc(sizeof(php_dio_win32_canon_data));\r
2686 +               memset(wdata->canon_data, 0, sizeof(php_dio_win32_canon_data));\r
2687 +               wdata->canon_data->size = DIO_WIN32_CANON_BUF_SIZE;\r
2688 +       }\r
2689 +\r
2690 +       return 1;\r
2691 +}\r
2692 +/* }}} */\r
2693 +\r
2694 +/* {{{ dio_serial_init\r
2695 + * Initialises the serial port\r
2696 + */\r
2697 +static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) {\r
2698 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2699 +       DWORD err, rate_def, data_bits_def, stop_bits_def, parity_def;\r
2700 +       DCB dcb;\r
2701 +\r
2702 +       if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {\r
2703 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%d) (%d)", data->data_rate, __LINE__);\r
2704 +               return 0;\r
2705 +       }\r
2706 +\r
2707 +       if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {\r
2708 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits);\r
2709 +               return 0;\r
2710 +       }\r
2711 +\r
2712 +       if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {\r
2713 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);\r
2714 +               return 0;\r
2715 +       }\r
2716 +\r
2717 +       if (!dio_parity_to_define(data->parity, &parity_def)) {\r
2718 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity);\r
2719 +               return 0;\r
2720 +       }\r
2721 +\r
2722 +       if (!GetCommState(wdata->handle, &(wdata->olddcb))) {\r
2723 +               err = GetLastError();\r
2724 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "GetCommState() failed! (%d)", err);\r
2725 +               return 0;\r
2726 +       }\r
2727 +\r
2728 +       /* Init the DCB structure */\r
2729 +       memset(&dcb, 0, sizeof(DCB));\r
2730 +       dcb.DCBlength = sizeof(DCB);\r
2731 +\r
2732 +       /* Set the communication parameters */\r
2733 +       dcb.fBinary  = 1;\r
2734 +       dcb.BaudRate = rate_def;\r
2735 +       dcb.ByteSize = (BYTE)data_bits_def;\r
2736 +       dcb.StopBits = (BYTE)stop_bits_def;\r
2737 +       dcb.Parity   = (BYTE)parity_def;\r
2738 +\r
2739 +       /* Set the control line parameters */\r
2740 +       dcb.fDtrControl       = DTR_CONTROL_DISABLE;\r
2741 +       dcb.fDsrSensitivity   = FALSE;\r
2742 +       dcb.fOutxDsrFlow      = FALSE;\r
2743 +       dcb.fTXContinueOnXoff = FALSE;\r
2744 +       dcb.fOutX             = FALSE;\r
2745 +       dcb.fInX              = FALSE;\r
2746 +       dcb.fErrorChar        = FALSE;\r
2747 +       dcb.fNull             = FALSE;\r
2748 +       dcb.fAbortOnError     = FALSE;\r
2749 +\r
2750 +       /* Hardware flow control */\r
2751 +       if (data->flow_control) {\r
2752 +               dcb.fOutxCtsFlow = TRUE;\r
2753 +               dcb.fRtsControl  = RTS_CONTROL_HANDSHAKE;\r
2754 +       } else {\r
2755 +               dcb.fOutxCtsFlow = FALSE;\r
2756 +               dcb.fRtsControl  = RTS_CONTROL_DISABLE;\r
2757 +       }\r
2758 +\r
2759 +       if (!SetCommState(wdata->handle, &dcb)) {\r
2760 +               return 0;\r
2761 +       }\r
2762 +\r
2763 +       return 1;\r
2764 +}\r
2765 +/* }}} */\r
2766 +\r
2767 +\r
2768 +/* {{{ dio_serial_uninit\r
2769 + * Restores the serial settings back to their original state.\r
2770 + */\r
2771 +int dio_serial_uninit(php_dio_stream_data *data) {\r
2772 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2773 +\r
2774 +       if (!SetCommState(wdata->handle, &(wdata->olddcb))) {\r
2775 +               return 0;\r
2776 +       }\r
2777 +\r
2778 +       return 1;\r
2779 +}\r
2780 +/* }}} */\r
2781 +\r
2782 +/* {{{ dio_serial_flush\r
2783 + * Purges the serial buffers of data.\r
2784 + */\r
2785 +int dio_serial_purge(php_dio_stream_data *data) {\r
2786 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2787 +       BOOL ret;\r
2788 +\r
2789 +       /* Purge the canonical buffer if required */\r
2790 +       if (data->canonical && ((wdata->desired_access & GENERIC_READ) == GENERIC_READ)) {\r
2791 +               wdata->canon_data->read_pos  = 0;\r
2792 +               wdata->canon_data->write_pos = 0;\r
2793 +       }\r
2794 +\r
2795 +       /* Purge the com port */\r
2796 +       if ((wdata->desired_access & (GENERIC_READ|GENERIC_WRITE)) == (GENERIC_READ|GENERIC_WRITE)) {\r
2797 +               ret = PurgeComm(wdata->handle, PURGE_RXCLEAR|PURGE_TXCLEAR);\r
2798 +       } else if ((wdata->desired_access & GENERIC_WRITE) == GENERIC_WRITE) {\r
2799 +               ret = PurgeComm(wdata->handle, PURGE_TXCLEAR);\r
2800 +       } else if ((wdata->desired_access & GENERIC_READ) == GENERIC_READ) {\r
2801 +               ret = PurgeComm(wdata->handle, PURGE_RXCLEAR);\r
2802 +       }\r
2803 +\r
2804 +       return ret;\r
2805 +}\r
2806 +/* }}} */\r
2807 +\r
2808 +/* {{{ dio_serial_open_stream\r
2809 + * Opens the underlying stream.\r
2810 + */\r
2811 +int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {\r
2812 +       php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;\r
2813 +       COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };\r
2814 +       DWORD err;\r
2815 +\r
2816 +       if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {\r
2817 +               return 0;\r
2818 +       }\r
2819 +\r
2820 +       if (!GetCommTimeouts(wdata->handle, &(wdata->oldcto))) {\r
2821 +               err = GetLastError();\r
2822 +               php_error_docref(NULL TSRMLS_CC, E_WARNING, "SetCommTimeouts() failed! (%d) Not a comm port?", err);\r
2823 +               CloseHandle(wdata->handle);\r
2824 +               return 0;\r
2825 +       }\r
2826 +\r
2827 +       /* If we're not blocking but don't have a timeout\r
2828 +          set to return immediately */\r
2829 +       if (!data->is_blocking && !data->has_timeout) {\r
2830 +               cto.ReadIntervalTimeout = MAXDWORD;\r
2831 +       }\r
2832 +       \r
2833 +       /* If we have a timeout ignore the blocking and set\r
2834 +          the total time in which to read the data */\r
2835 +       if (data->has_timeout) {\r
2836 +               cto.ReadIntervalTimeout = MAXDWORD;\r
2837 +               cto.ReadTotalTimeoutMultiplier  = MAXDWORD;\r
2838 +               cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) + \r
2839 +                       (data->timeout_sec * 1000);\r
2840 +       }\r
2841 +\r
2842 +       if (!SetCommTimeouts(wdata->handle, &cto)) {\r
2843 +               CloseHandle(wdata->handle);\r
2844 +               return 0;\r
2845 +       }\r
2846 +\r
2847 +       if (!dio_serial_init(data TSRMLS_CC)) {\r
2848 +               CloseHandle(wdata->handle);\r
2849 +               return 0;\r
2850 +       }\r
2851 +\r
2852 +       return 1;\r
2853 +}\r
2854 +/* }}} */\r
2855 +\r
2856 +/*\r
2857 + * Local variables:\r
2858 + * c-basic-offset: 4\r
2859 + * tab-width: 4\r
2860 + * End:\r
2861 + * vim600: fdm=marker\r
2862 + * vim: sw=4 ts=4 noet\r
2863 + */\r
2864 --- /dev/null
2865 +++ b/ext/dio/php_dio.h
2866 @@ -0,0 +1,60 @@
2867 +/*
2868 +   +----------------------------------------------------------------------+
2869 +   | PHP Version 5                                                        |
2870 +   +----------------------------------------------------------------------+
2871 +   | Copyright (c) 1997-2004 The PHP Group                                |
2872 +   +----------------------------------------------------------------------+
2873 +   | This source file is subject to version 3.0 of the PHP license,       |
2874 +   | that is bundled with this package in the file LICENSE, and is        |
2875 +   | available through the world-wide-web at the following url:           |
2876 +   | http://www.php.net/license/3_0.txt.                                  |
2877 +   | If you did not receive a copy of the PHP license and are unable to   |
2878 +   | obtain it through the world-wide-web, please send a note to          |
2879 +   | license@php.net so we can mail you a copy immediately.               |
2880 +   +----------------------------------------------------------------------+
2881 + */
2882 +
2883 +#ifndef PHP_DIO_H
2884 +#define PHP_DIO_H
2885 +
2886 +#include "php.h"
2887 +#include "php_dio_common.h"
2888 +#include "php_dio_stream_wrappers.h"
2889 +
2890 +extern zend_module_entry dio_module_entry;
2891 +#define phpext_dio_ptr &dio_module_entry
2892 +
2893 +#define PHP_DIO_VERSION "0.0.4RC4"
2894 +
2895 +/* Standard module functions. */
2896 +PHP_MINIT_FUNCTION(dio);
2897 +PHP_MSHUTDOWN_FUNCTION(dio);
2898 +PHP_RINIT_FUNCTION(dio);
2899 +PHP_RSHUTDOWN_FUNCTION(dio);
2900 +PHP_MINFO_FUNCTION(dio);
2901 +
2902 +/* Legacy functions. */
2903 +PHP_FUNCTION(dio_open);
2904 +PHP_FUNCTION(dio_truncate);
2905 +PHP_FUNCTION(dio_stat);
2906 +PHP_FUNCTION(dio_seek);
2907 +PHP_FUNCTION(dio_read);
2908 +PHP_FUNCTION(dio_write);
2909 +PHP_FUNCTION(dio_fcntl);
2910 +PHP_FUNCTION(dio_close);
2911 +PHP_FUNCTION(dio_tcsetattr);
2912 +
2913 +typedef struct {
2914 +       int fd;
2915 +} php_fd_t;
2916 +
2917 +#endif
2918 +
2919 +
2920 +/*
2921 + * Local variables:
2922 + * tab-width: 4
2923 + * c-basic-offset: 4
2924 + * indent-tabs-mode: t
2925 + * End:
2926 + */
2927 --- /dev/null
2928 +++ b/ext/dio/php_dio_common.h
2929 @@ -0,0 +1,77 @@
2930 +/*
2931 +   +----------------------------------------------------------------------+
2932 +   | PHP Version 5                                                        |
2933 +   +----------------------------------------------------------------------+
2934 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |
2935 +   +----------------------------------------------------------------------+
2936 +   | This source file is subject to version 3.0 of the PHP license,       |
2937 +   | that is bundled with this package in the file LICENSE, and is        |
2938 +   | available through the world-wide-web at the following url:           |
2939 +   | http://www.php.net/license/3_0.txt.                                  |
2940 +   | If you did not receive a copy of the PHP license and are unable to   |
2941 +   | obtain it through the world-wide-web, please send a note to          |
2942 +   | license@php.net so we can mail you a copy immediately.               |
2943 +   +----------------------------------------------------------------------+
2944 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |
2945 +   +----------------------------------------------------------------------+
2946 + */
2947 +
2948 +#ifndef PHP_DIO_COMMON_H_
2949 +#define PHP_DIO_COMMON_H_
2950 +
2951 +#ifdef PHP_WIN32
2952 +#define PHP_DIO_API __declspec(dllexport)
2953 +#else
2954 +#define PHP_DIO_API
2955 +#endif
2956 +
2957 +#ifdef PHP_WIN32
2958 +#include "php_dio_win32.h"
2959 +#else
2960 +#include "php_dio_posix.h"
2961 +#endif
2962 +
2963 +#define DIO_STREAM_TYPE_NONE   0
2964 +#define DIO_STREAM_TYPE_RAW    1
2965 +#define DIO_STREAM_TYPE_SERIAL 2
2966 +
2967 +long dio_convert_to_long(zval *val);
2968 +
2969 +php_dio_stream_data * dio_create_stream_data(void);
2970 +
2971 +void dio_init_stream_data(php_dio_stream_data *data);
2972 +
2973 +void dio_assoc_array_get_basic_options(zval *options, php_dio_stream_data *data TSRMLS_DC);
2974 +
2975 +void dio_assoc_array_get_serial_options(zval *options, php_dio_stream_data *data TSRMLS_DC);
2976 +
2977 +void dio_stream_context_get_basic_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC);
2978 +
2979 +void dio_stream_context_get_serial_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC);
2980 +
2981 +size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count);
2982 +
2983 +size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count);
2984 +
2985 +int dio_common_close(php_dio_stream_data *data);
2986 +
2987 +int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam);
2988 +
2989 +int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC);
2990 +
2991 +int dio_serial_uninit(php_dio_stream_data *data);
2992 +
2993 +int dio_serial_purge(php_dio_stream_data *data);
2994 +
2995 +int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC);
2996 +
2997 +#endif /* PHP_DIO_COMMON_H_ */
2998 +
2999 +/*
3000 + * Local variables:
3001 + * c-basic-offset: 4
3002 + * tab-width: 4
3003 + * End:
3004 + * vim600: fdm=marker
3005 + * vim: sw=4 ts=4 noet
3006 + */
3007 --- /dev/null
3008 +++ b/ext/dio/php_dio_common_data.h
3009 @@ -0,0 +1,59 @@
3010 +/*
3011 +   +----------------------------------------------------------------------+
3012 +   | PHP Version 5                                                        |
3013 +   +----------------------------------------------------------------------+
3014 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |
3015 +   +----------------------------------------------------------------------+
3016 +   | This source file is subject to version 3.0 of the PHP license,       |
3017 +   | that is bundled with this package in the file LICENSE, and is        |
3018 +   | available through the world-wide-web at the following url:           |
3019 +   | http://www.php.net/license/3_0.txt.                                  |
3020 +   | If you did not receive a copy of the PHP license and are unable to   |
3021 +   | obtain it through the world-wide-web, please send a note to          |
3022 +   | license@php.net so we can mail you a copy immediately.               |
3023 +   +----------------------------------------------------------------------+
3024 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |
3025 +   +----------------------------------------------------------------------+
3026 + */
3027 +
3028 +#ifndef PHP_DIO_COMMON_DATA_H_
3029 +#define PHP_DIO_COMMON_DATA_H_
3030 +
3031 +/* This is the data structure 'base class'.  It is common data fields used
3032 + * by all versions of DIO.
3033 + */
3034 +typedef struct _php_dio_stream_data {
3035 +       /* Stream type */
3036 +       int stream_type;
3037 +       /* Stream options */
3038 +       int end_of_file;
3039 +#ifdef DIO_HAS_FILEPERMS
3040 +       int has_perms;
3041 +       int perms;
3042 +#endif
3043 +#ifdef DIO_NONBLOCK
3044 +       int is_blocking;
3045 +       int has_timeout;
3046 +       long timeout_sec;
3047 +       long timeout_usec;
3048 +       int timed_out;
3049 +#endif
3050 +       /* Serial options */
3051 +       long data_rate;
3052 +       int data_bits;
3053 +       int stop_bits;
3054 +       int parity;
3055 +       int flow_control;
3056 +       int canonical;
3057 +} php_dio_stream_data ;
3058 +
3059 +#endif /* PHP_DIO_COMMON_DATA_H_ */
3060 +
3061 +/*
3062 + * Local variables:
3063 + * c-basic-offset: 4
3064 + * tab-width: 4
3065 + * End:
3066 + * vim600: fdm=marker
3067 + * vim: sw=4 ts=4 noet
3068 + */
3069 --- /dev/null
3070 +++ b/ext/dio/php_dio_posix.h
3071 @@ -0,0 +1,70 @@
3072 +/*\r
3073 +   +----------------------------------------------------------------------+\r
3074 +   | PHP Version 5                                                        |\r
3075 +   +----------------------------------------------------------------------+\r
3076 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |\r
3077 +   +----------------------------------------------------------------------+\r
3078 +   | This source file is subject to version 3.0 of the PHP license,       |\r
3079 +   | that is bundled with this package in the file LICENSE, and is        |\r
3080 +   | available through the world-wide-web at the following url:           |\r
3081 +   | http://www.php.net/license/3_0.txt.                                  |\r
3082 +   | If you did not receive a copy of the PHP license and are unable to   |\r
3083 +   | obtain it through the world-wide-web, please send a note to          |\r
3084 +   | license@php.net so we can mail you a copy immediately.               |\r
3085 +   +----------------------------------------------------------------------+\r
3086 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |\r
3087 +   +----------------------------------------------------------------------+\r
3088 + */\r
3089 +\r
3090 +#ifndef PHP_DIO_POSIX_H_\r
3091 +#define PHP_DIO_POSIX_H_\r
3092 +\r
3093 +#include <sys/stat.h>\r
3094 +#include <sys/types.h>\r
3095 +#include <sys/select.h>\r
3096 +#include <sys/time.h>\r
3097 +\r
3098 +#ifdef HAVE_UNISTD_H\r
3099 +#include <unistd.h>\r
3100 +#endif\r
3101 +\r
3102 +#include <fcntl.h>\r
3103 +#include <termios.h>\r
3104 +\r
3105 +\r
3106 +/**\r
3107 + * Detect if we can support non blocking IO.
3108 + */\r
3109 +#ifdef O_NONBLOCK\r
3110 +#define DIO_NONBLOCK O_NONBLOCK\r
3111 +#else\r
3112 +#ifdef O_NDELAY\r
3113 +#define DIO_NONBLOCK O_NDELAY\r
3114 +#endif\r
3115 +#endif\r
3116 +\r
3117 +/**\r
3118 + * POSIXy platforms have file permissions
3119 + */\r
3120 +#define DIO_HAS_FILEPERMS\r
3121 +\r
3122 +#include "php_dio_common_data.h"\r
3123 +\r
3124 +typedef struct _php_dio_posix_stream_data {\r
3125 +       php_dio_stream_data common;\r
3126 +       int fd;\r
3127 +       int flags;\r
3128 +       /* Serial options */\r
3129 +       struct termios oldtio;\r
3130 +} php_dio_posix_stream_data ;\r
3131 +\r
3132 +#endif /* PHP_DIO_POSIX_H_ */\r
3133 +\r
3134 +/*\r
3135 + * Local variables:\r
3136 + * c-basic-offset: 4\r
3137 + * tab-width: 4\r
3138 + * End:\r
3139 + * vim600: fdm=marker\r
3140 + * vim: sw=4 ts=4 noet\r
3141 + */\r
3142 --- /dev/null
3143 +++ b/ext/dio/php_dio_stream_wrappers.h
3144 @@ -0,0 +1,51 @@
3145 +/*
3146 +   +----------------------------------------------------------------------+
3147 +   | PHP Version 5                                                        |
3148 +   +----------------------------------------------------------------------+
3149 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |
3150 +   +----------------------------------------------------------------------+
3151 +   | This source file is subject to version 3.0 of the PHP license,       |
3152 +   | that is bundled with this package in the file LICENSE, and is        |
3153 +   | available through the world-wide-web at the following url:           |
3154 +   | http://www.php.net/license/3_0.txt.                                  |
3155 +   | If you did not receive a copy of the PHP license and are unable to   |
3156 +   | obtain it through the world-wide-web, please send a note to          |
3157 +   | license@php.net so we can mail you a copy immediately.               |
3158 +   +----------------------------------------------------------------------+
3159 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |
3160 +   +----------------------------------------------------------------------+
3161 + */
3162 +
3163 +#ifndef PHP_DIO_STREAM_WRAPPERS_H_
3164 +#define PHP_DIO_STREAM_WRAPPERS_H_
3165 +
3166 +#define DIO_RAW_STREAM_NAME         "dio.raw"
3167 +#define DIO_RAW_STREAM_PROTOCOL     "dio.raw://"
3168 +#define DIO_SERIAL_STREAM_NAME      "dio.serial"
3169 +#define DIO_SERIAL_STREAM_PROTOCOL  "dio.serial://"
3170 +
3171 +/* To support PHP 5.4 and later */
3172 +#if PHP_VERSION_ID < 50399
3173 +#define DIO_SAFE_MODE_CHECK(f, m) (PG(safe_mode) && !php_checkuid(f, m, CHECKUID_CHECK_MODE_PARAM))
3174 +#else
3175 +#define DIO_SAFE_MODE_CHECK(f, m) (0)
3176 +#endif
3177 +
3178 +extern php_stream_wrapper php_dio_raw_stream_wrapper;
3179 +
3180 +PHP_FUNCTION(dio_raw);
3181 +
3182 +extern php_stream_wrapper php_dio_serial_stream_wrapper;
3183 +
3184 +PHP_FUNCTION(dio_serial);
3185 +
3186 +#endif /* PHP_DIO_STREAM_WRAPPERS_H_ */
3187 +
3188 +/*
3189 + * Local variables:
3190 + * c-basic-offset: 4
3191 + * tab-width: 4
3192 + * End:
3193 + * vim600: fdm=marker
3194 + * vim: sw=4 ts=4 noet
3195 + */
3196 --- /dev/null
3197 +++ b/ext/dio/php_dio_win32.h
3198 @@ -0,0 +1,62 @@
3199 +/*\r
3200 +   +----------------------------------------------------------------------+\r
3201 +   | PHP Version 5                                                        |\r
3202 +   +----------------------------------------------------------------------+\r
3203 +   | Copyright (c) 2009 Melanie Rhianna Lewis                             |\r
3204 +   +----------------------------------------------------------------------+\r
3205 +   | This source file is subject to version 3.0 of the PHP license,       |\r
3206 +   | that is bundled with this package in the file LICENSE, and is        |\r
3207 +   | available through the world-wide-web at the following url:           |\r
3208 +   | http://www.php.net/license/3_0.txt.                                  |\r
3209 +   | If you did not receive a copy of the PHP license and are unable to   |\r
3210 +   | obtain it through the world-wide-web, please send a note to          |\r
3211 +   | license@php.net so we can mail you a copy immediately.               |\r
3212 +   +----------------------------------------------------------------------+\r
3213 +   | Author: Melanie Rhianna Lewis <cyberspice@php.net>                   |\r
3214 +   +----------------------------------------------------------------------+\r
3215 + */\r
3216 +\r
3217 +#ifndef PHP_DIO_WIN32_H_\r
3218 +#define PHP_DIO_WIN32_H_\r
3219 +\r
3220 +#include <windows.h>\r
3221 +\r
3222 +/* Windows platform can do non blocking. */\r
3223 +#define DIO_NONBLOCK\r
3224 +\r
3225 +#include "php_dio_common_data.h"\r
3226 +\r
3227 +#define DIO_WIN32_CANON_BUF_SIZE 8192\r
3228 +\r
3229 +/* This is the buffer information when reading in canonical mode.  Data is \r
3230 +   read right up to either buffer being full or a newline being read.  Excess\r
3231 +   data will be retained in the buffer until the next read. */\r
3232 +typedef struct _php_dio_win32_canon_data {\r
3233 +       size_t size;\r
3234 +       size_t read_pos;\r
3235 +       size_t write_pos;\r
3236 +       char buf[DIO_WIN32_CANON_BUF_SIZE];\r
3237 +\r
3238 +} php_dio_win32_canon_data;\r
3239 +\r
3240 +typedef struct _php_dio_win32_stream_data {\r
3241 +       php_dio_stream_data common;\r
3242 +       HANDLE handle;\r
3243 +       DWORD desired_access;\r
3244 +       DWORD creation_disposition;\r
3245 +       DCB olddcb;\r
3246 +       COMMTIMEOUTS oldcto;\r
3247 +       php_dio_win32_canon_data *canon_data;\r
3248 +\r
3249 +} php_dio_win32_stream_data ;\r
3250 +\r
3251 +#endif /* PHP_DIO_WIN32_H_ */\r
3252 +\r
3253 +/*\r
3254 + * Local variables:\r
3255 + * c-basic-offset: 4\r
3256 + * tab-width: 4\r
3257 + * End:\r
3258 + * vim600: fdm=marker\r
3259 + * vim: sw=4 ts=4 noet\r
3260 + */\r
3261 --- /dev/null
3262 +++ b/ext/dio/tests/001.phpt
3263 @@ -0,0 +1,23 @@
3264 +--TEST--
3265 +Test dio legacy open
3266 +--SKIPIF--
3267 +<?php if (!extension_loaded("dio")) print "skip"; ?>
3268 +--FILE--
3269 +<?php 
3270 +       $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); 
3271 +
3272 +       if (!$iswin) {
3273 +               $filename = "/dev/null";
3274 +       } else {
3275 +               $filename = "NUL";
3276 +       }
3277 +       
3278 +       $f = dio_open($filename,O_RDONLY);
3279 +       if ($f) {
3280 +               echo "Legacy open passed";
3281 +       } else {
3282 +               echo "Legacy open failed";
3283 +       }
3284 +?>
3285 +--EXPECT--
3286 +Legacy open passed
3287 --- /dev/null
3288 +++ b/ext/dio/tests/dio_raw_stream_001.phpt
3289 @@ -0,0 +1,24 @@
3290 +--TEST--
3291 +Test dio raw stream open
3292 +--SKIPIF--
3293 +<?php if (!extension_loaded("dio")) print "skip"; ?>
3294 +--FILE--
3295 +<?php
3296 +       $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); 
3297 +
3298 +       if (!$iswin) {
3299 +               $filename = "dio.raw:///dev/null";
3300 +       } else {
3301 +               $filename = "dio.raw://NUL";
3302 +       }
3303 +       
3304 +       $f = fopen($filename, "r+");
3305 +       if ($f) {
3306 +               echo "Raw open passed";
3307 +               fclose($f);
3308 +       } else {
3309 +               echo "Raw open failed";
3310 +       }
3311 +?>
3312 +--EXPECT--
3313 +Raw open passed
3314 --- /dev/null
3315 +++ b/ext/dio/tests/dio_raw_stream_002.phpt
3316 @@ -0,0 +1,27 @@
3317 +--TEST--
3318 +Test dio raw stream close
3319 +--SKIPIF--
3320 +<?php if (!extension_loaded("dio")) print "skip"; ?>
3321 +--FILE--
3322 +<?php 
3323 +       $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); 
3324 +
3325 +       if (!$iswin) {
3326 +               $filename = "dio.raw:///dev/null";
3327 +       } else {
3328 +               $filename = "dio.raw://NUL";
3329 +       }
3330 +
3331 +       $f = fopen($filename, "r+");
3332 +       if ($f) {
3333 +               if (fclose($f)) {
3334 +                       echo "Raw close passed";
3335 +               } else {
3336 +                       echo "Raw close failed";
3337 +               }
3338 +       } else {
3339 +               echo "Raw open failed";
3340 +       }
3341 +?>
3342 +--EXPECT--
3343 +Raw close passed
3344 --- /dev/null
3345 +++ b/ext/dio/tests/dio_raw_stream_003.phpt
3346 @@ -0,0 +1,29 @@
3347 +--TEST--
3348 +Test dio raw stream write
3349 +--SKIPIF--
3350 +<?php if (!extension_loaded("dio")) print "skip"; ?>
3351 +--FILE--
3352 +<?php 
3353 +       $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); 
3354 +
3355 +       if (!$iswin) {
3356 +               $filename = "dio.raw:///dev/null";
3357 +       } else {
3358 +               $filename = "dio.raw://NUL";
3359 +       }
3360 +
3361 +       $f = fopen($filename, "r+");
3362 +       if ($f) {
3363 +               $data = str_repeat("+", 2048);
3364 +               if (fwrite($f, $data)) {
3365 +                       echo "Raw write passed";
3366 +               } else {
3367 +                       echo "Raw write failed";
3368 +               }
3369 +               fclose($f);
3370 +       } else {
3371 +               echo "Raw open failed";
3372 +       }
3373 +?>
3374 +--EXPECT--
3375 +Raw write passed
3376 --- /dev/null
3377 +++ b/ext/dio/tests/dio_raw_stream_004.phpt
3378 @@ -0,0 +1,46 @@
3379 +--TEST--
3380 +Test dio raw read
3381 +--SKIPIF--
3382 +<?php
3383 +       if (!extension_loaded('dio')) print 'skip';
3384 +?>
3385 +--FILE--
3386 +<?php 
3387 +       // Create a temp file with some content to read
3388 +
3389 +       // Create the temp file name
3390 +       if (!function_exists('sys_get_temp_dir')) {
3391 +               if (!($tmpdir = getenv('TEMP'))) {
3392 +                       $tmpdir = '';
3393 +               }
3394 +       } else {
3395 +               $tmpdir = sys_get_temp_dir();
3396 +       }
3397 +       $filename = tempnam($tmpdir, 'dio_raw_stream_004.tmp');
3398 +                       
3399 +       // Create the temp file
3400 +       $tf = fopen($filename, "w");
3401 +       if ($tf) {
3402 +               fwrite($tf, str_repeat('*', 2048));     
3403 +               fclose($tf);
3404 +       } else {
3405 +               echo "Can\'t create temp file";
3406 +       }
3407 +
3408 +       $f = fopen('dio.raw://' . $filename, "r");
3409 +       if ($f) {
3410 +               $data = fread($f, 2048);
3411 +               if ($data && (strlen($data) == 2048)) {
3412 +                       echo "Raw read passed";
3413 +               } else {
3414 +                       echo "Raw read failed";
3415 +               }
3416 +               fclose($f);
3417 +       } else {
3418 +               echo "Raw open failed";
3419 +       }
3420 +
3421 +       unlink($filename);
3422 +?>
3423 +--EXPECT--
3424 +Raw read passed
3425 --- /dev/null
3426 +++ b/ext/dio/tests/dio_raw_stream_005.phpt
3427 @@ -0,0 +1,45 @@
3428 +--TEST--
3429 +Test dio eof read
3430 +--SKIPIF--
3431 +<?php
3432 +       if (!extension_loaded('dio')) print 'skip';
3433 +?>
3434 +--FILE--
3435 +<?php 
3436 +       // Create a temp file with some content to read
3437 +
3438 +       // Create the temp file name
3439 +       if (!function_exists('sys_get_temp_dir')) {
3440 +               if (!($tmpdir = getenv('TEMP'))) {
3441 +                       $tmpdir = '';
3442 +               }
3443 +       } else {
3444 +               $tmpdir = sys_get_temp_dir();
3445 +       }
3446 +       $filename = tempnam($tmpdir, 'dio_raw_stream_005.tmp');
3447 +                       
3448 +       // Create the temp file
3449 +       $tf = fopen($filename, "w");
3450 +       if ($tf) {
3451 +               fclose($tf);
3452 +       } else {
3453 +               echo "Can\'t create temp file";
3454 +       }
3455 +
3456 +       $f = fopen('dio.raw://' . $filename, "r");
3457 +       if ($f) {
3458 +               $data = fread($f, 2048);
3459 +               if (feof($f)) {
3460 +                       echo "Raw feof passed";
3461 +               } else {
3462 +                       echo "Raw feof failed";
3463 +               }
3464 +               fclose($f);
3465 +       } else {
3466 +               echo "Raw open failed";
3467 +       }
3468 +
3469 +       unlink($filename);
3470 +?>
3471 +--EXPECT--
3472 +Raw feof passed
3473 --- /dev/null
3474 +++ b/ext/dio/tests/dio_raw_stream_006.phpt
3475 @@ -0,0 +1,46 @@
3476 +--TEST--
3477 +Test dio raw read
3478 +--SKIPIF--
3479 +<?php
3480 +       if (!extension_loaded('dio')) print 'skip';
3481 +?>
3482 +--FILE--
3483 +<?php 
3484 +       // Create a temp file with some content to read
3485 +
3486 +       // Create the temp file name
3487 +       if (!function_exists('sys_get_temp_dir')) {
3488 +               if (!($tmpdir = getenv('TEMP'))) {
3489 +                       $tmpdir = '';
3490 +               }
3491 +       } else {
3492 +               $tmpdir = sys_get_temp_dir();
3493 +       }
3494 +       $filename = tempnam($tmpdir, 'diotest');
3495 +                       
3496 +       // Create the temp file
3497 +       $tf = fopen($filename, "w");
3498 +       if ($tf) {
3499 +               fwrite($tf, str_repeat('*', 2048));     
3500 +               fclose($tf);
3501 +       } else {
3502 +               echo "Can\'t create temp file";
3503 +       }
3504 +
3505 +       $f = fopen('dio.raw://' . $filename, "r");
3506 +       if ($f) {
3507 +               $data = fread($f, 1024);
3508 +               if (stream_set_blocking($f, false)) {
3509 +                       echo "Raw set blocking passed";
3510 +               } else {
3511 +                       echo "Raw set blocking failed";
3512 +               }
3513 +               fclose($f);
3514 +       } else {
3515 +               echo "Raw open failed";
3516 +       }
3517 +
3518 +       unlink($filename);
3519 +?>
3520 +--EXPECT--
3521 +Raw set blocking passed
3522 --- /dev/null
3523 +++ b/ext/dio/tests/dio_raw_stream_007.phpt
3524 @@ -0,0 +1,22 @@
3525 +--TEST--
3526 +Test dio_raw() call
3527 +--SKIPIF--
3528 +<?php if (!extension_loaded("dio")) print "skip"; ?>
3529 +--FILE--
3530 +<?php
3531 +       $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); 
3532 +
3533 +       if (!$iswin) {
3534 +               $filename = "/dev/null";
3535 +       } else {
3536 +               $filename = "NUL";
3537 +       }
3538 +
3539 +       $f = dio_raw($filename, "r+");
3540 +       if ($f) {
3541 +               echo "dio_raw passed";
3542 +               fclose($f);
3543 +       }
3544 +?>
3545 +--EXPECT--
3546 +dio_raw passed