/RISCOS/Modules/riscosmodule.c

http://unladen-swallow.googlecode.com/ · C · 603 lines · 521 code · 59 blank · 23 comment · 109 complexity · ea1a258a4c8401dd4aaacbb0edd8a85c MD5 · raw file

  1. /* RISCOS module implementation */
  2. #include "oslib/osfscontrol.h"
  3. #include "oslib/osgbpb.h"
  4. #include "oslib/os.h"
  5. #include "oslib/osfile.h"
  6. #include "unixstuff.h"
  7. #include <sys/fcntl.h>
  8. #include "Python.h"
  9. #include "structseq.h"
  10. #include <errno.h>
  11. static os_error *e;
  12. /*static PyObject *RiscosError;*/ /* Exception riscos.error */
  13. static PyObject *riscos_error(char *s)
  14. {
  15. PyErr_SetString(PyExc_OSError, s);
  16. return NULL;
  17. }
  18. static PyObject *riscos_oserror(void)
  19. {
  20. return riscos_error(e->errmess);
  21. }
  22. /* RISCOS file commands */
  23. static PyObject *
  24. riscos_remove(PyObject *self, PyObject *args)
  25. {
  26. char *path1;
  27. if (!PyArg_ParseTuple(args, "s:remove", &path1)) return NULL;
  28. if (remove(path1)) return PyErr_SetFromErrno(PyExc_OSError);
  29. Py_INCREF(Py_None);
  30. return Py_None;
  31. }
  32. static PyObject *
  33. riscos_rename(PyObject *self, PyObject *args)
  34. {
  35. char *path1, *path2;
  36. if (!PyArg_ParseTuple(args, "ss:rename", &path1, &path2))
  37. return NULL;
  38. if (rename(path1,path2)) return PyErr_SetFromErrno(PyExc_OSError);
  39. Py_INCREF(Py_None);
  40. return Py_None;
  41. }
  42. static PyObject *
  43. riscos_system(PyObject *self, PyObject *args)
  44. {
  45. char *command;
  46. if (!PyArg_ParseTuple(args, "s:system", &command)) return NULL;
  47. return PyInt_FromLong(system(command));
  48. }
  49. static PyObject *
  50. riscos_chdir(PyObject *self, PyObject *args)
  51. {
  52. char *path;
  53. if (!PyArg_ParseTuple(args, "s:chdir", &path)) return NULL;
  54. e=xosfscontrol_dir(path);
  55. if(e) return riscos_oserror();
  56. Py_INCREF(Py_None);
  57. return Py_None;
  58. }
  59. static PyObject *
  60. canon(char *path)
  61. {
  62. int len;
  63. PyObject *obj;
  64. char *buf;
  65. e=xosfscontrol_canonicalise_path(path,0,0,0,0,&len);
  66. if(e) return riscos_oserror();
  67. obj=PyString_FromStringAndSize(NULL,-len);
  68. if(obj==NULL) return NULL;
  69. buf=PyString_AsString(obj);
  70. e=xosfscontrol_canonicalise_path(path,buf,0,0,1-len,&len);
  71. if(len!=1) return riscos_error("Error expanding path");
  72. if(!e) return obj;
  73. Py_DECREF(obj);
  74. return riscos_oserror();
  75. }
  76. static PyObject *
  77. riscos_getcwd(PyObject *self, PyObject *unused)
  78. {
  79. return canon("@");
  80. }
  81. static PyObject *
  82. riscos_expand(PyObject *self, PyObject *args)
  83. {
  84. char *path;
  85. if (!PyArg_ParseTuple(args, "s:expand", &path)) return NULL;
  86. return canon(path);
  87. }
  88. static PyObject *
  89. riscos_mkdir(PyObject *self, PyObject *args)
  90. {
  91. char *path;
  92. int mode;
  93. if (!PyArg_ParseTuple(args, "s|i:mkdir", &path, &mode)) return NULL;
  94. e=xosfile_create_dir(path,0);
  95. if(e) return riscos_oserror();
  96. Py_INCREF(Py_None);
  97. return Py_None;
  98. }
  99. static PyObject *
  100. riscos_listdir(PyObject *self, PyObject *args)
  101. {
  102. char *path,buf[256];
  103. PyObject *d, *v;
  104. int c=0,count;
  105. if (!PyArg_ParseTuple(args, "s:listdir", &path)) return NULL;
  106. d=PyList_New(0);
  107. if(!d) return NULL;
  108. for(;;)
  109. { e=xosgbpb_dir_entries(path,(osgbpb_string_list*)buf,
  110. 1,c,256,0,&count,&c);
  111. if(e)
  112. { Py_DECREF(d);return riscos_oserror();
  113. }
  114. if(count)
  115. { v=PyString_FromString(buf);
  116. if(!v) { Py_DECREF(d);return 0;}
  117. if(PyList_Append(d,v)) {Py_DECREF(d);Py_DECREF(v);return 0;}
  118. }
  119. if(c==-1) break;
  120. }
  121. return d;
  122. }
  123. PyDoc_STRVAR(stat_result__doc__,
  124. "stat_result: Result from stat or lstat.\n\n\
  125. This object may be accessed either as a tuple of\n\
  126. (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
  127. or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
  128. \n\
  129. RiscOS: The fields st_ftype, st_attrs, and st_obtype are also available.\n\
  130. \n\
  131. See os.stat for more information.");
  132. static PyStructSequence_Field stat_result_fields[] = {
  133. { "st_mode", "protection bits" },
  134. { "st_ino", "inode" },
  135. { "st_dev", "device" },
  136. { "st_nlink", "number of hard links" },
  137. { "st_uid", "user ID of owner" },
  138. { "st_gid", "group ID of owner" },
  139. { "st_size", "total size, in bytes" },
  140. { "st_atime", "time of last access" },
  141. { "st_mtime", "time of last modification" },
  142. { "st_ctime", "time of last change" },
  143. { "st_ftype", "file type" },
  144. { "st_attrs", "attributes" },
  145. { "st_obtype", "object type" },
  146. { 0 }
  147. };
  148. static PyStructSequence_Desc stat_result_desc = {
  149. "riscos.stat_result",
  150. stat_result__doc__,
  151. stat_result_fields,
  152. 13
  153. };
  154. static PyTypeObject StatResultType;
  155. static PyObject *
  156. riscos_stat(PyObject *self, PyObject *args)
  157. {
  158. PyObject *v;
  159. char *path;
  160. int ob,len;
  161. bits t=0;
  162. bits ld,ex,at,ft,mode;
  163. if (!PyArg_ParseTuple(args, "s:stat", &path)) return NULL;
  164. e=xosfile_read_stamped_no_path(path,&ob,&ld,&ex,&len,&at,&ft);
  165. if(e) return riscos_oserror();
  166. switch (ob)
  167. { case osfile_IS_FILE:mode=0100000;break; /* OCTAL */
  168. case osfile_IS_DIR:mode=040000;break;
  169. case osfile_IS_IMAGE:mode=0140000;break;
  170. default:return riscos_error("Not found");
  171. }
  172. if(ft!=-1) t=unixtime(ld,ex);
  173. mode|=(at&7)<<6;
  174. mode|=((at&112)*9)>>4;
  175. v = PyStructSequence_New(&StatResultType);
  176. PyStructSequence_SET_ITEM(v, 0,
  177. PyInt_FromLong((long) mode)); /*st_mode*/
  178. PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) 0)); /*st_ino*/
  179. PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) 0)); /*st_dev*/
  180. PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) 0)); /*st_nlink*/
  181. PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) 0)); /*st_uid*/
  182. PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) 0)); /*st_gid*/
  183. PyStructSequence_SET_ITEM(v, 6,
  184. PyInt_FromLong((long) len)); /*st_size*/
  185. PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) t)); /*st_atime*/
  186. PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) t)); /*st_mtime*/
  187. PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) t)); /*st_ctime*/
  188. PyStructSequence_SET_ITEM(v, 10,
  189. PyInt_FromLong((long) ft)); /*file type*/
  190. PyStructSequence_SET_ITEM(v, 11,
  191. PyInt_FromLong((long) at)); /*attributes*/
  192. PyStructSequence_SET_ITEM(v, 12,
  193. PyInt_FromLong((long) ob)); /*object type*/
  194. if (PyErr_Occurred()) {
  195. Py_DECREF(v);
  196. return NULL;
  197. }
  198. return v;
  199. }
  200. static PyObject *
  201. riscos_chmod(PyObject *self,PyObject *args)
  202. {
  203. char *path;
  204. bits mode;
  205. bits attr;
  206. attr=(mode&0x700)>>8;
  207. attr|=(mode&7)<<4;
  208. if (!PyArg_ParseTuple(args, "si:chmod", &path,(int*)&mode)) return NULL;
  209. e=xosfile_write_attr(path,attr);
  210. if(e) return riscos_oserror();
  211. Py_INCREF(Py_None);
  212. return Py_None;
  213. }
  214. static PyObject *
  215. riscos_utime(PyObject *self, PyObject *args)
  216. {
  217. char *path;
  218. long atime, mtime;
  219. PyObject* arg;
  220. if (!PyArg_ParseTuple(args, "sO:utime", &path, &arg))
  221. return NULL;
  222. if (arg == Py_None) {
  223. /* optional time values not given */
  224. Py_BEGIN_ALLOW_THREADS
  225. e=xosfile_stamp(path);
  226. Py_END_ALLOW_THREADS
  227. if(e) return riscos_oserror();
  228. }
  229. else if (!PyArg_Parse(arg, "(ll)", &atime, &mtime)) {
  230. PyErr_SetString(PyExc_TypeError,
  231. "utime() arg 2 must be a tuple (atime, mtime)");
  232. return NULL;
  233. }
  234. else {
  235. /* catalogue info*/
  236. fileswitch_object_type obj_type;
  237. bits load_addr, exec_addr;
  238. int size;
  239. fileswitch_attr attr;
  240. /* read old catalogue info */
  241. Py_BEGIN_ALLOW_THREADS
  242. e=xosfile_read_no_path(path, &obj_type, &load_addr, &exec_addr, &size, &attr);
  243. Py_END_ALLOW_THREADS
  244. if(e) return riscos_oserror();
  245. /* check if load and exec address really contain filetype and date */
  246. if ( (load_addr & 0xFFF00000U) != 0xFFF00000U)
  247. return riscos_error("can't set date for object with load and exec addresses");
  248. /* convert argument mtime to RISC OS load and exec address */
  249. if(acorntime(&exec_addr, &load_addr, (time_t) mtime))
  250. return riscos_oserror();
  251. /* write new load and exec address */
  252. Py_BEGIN_ALLOW_THREADS
  253. e = xosfile_write(path, load_addr, exec_addr, attr);
  254. Py_END_ALLOW_THREADS
  255. if(e) return riscos_oserror();
  256. }
  257. Py_INCREF(Py_None);
  258. return Py_None;
  259. }
  260. static PyObject *
  261. riscos_settype(PyObject *self, PyObject *args)
  262. {
  263. char *path,*name;
  264. int type;
  265. if (!PyArg_ParseTuple(args, "si:settype", &path,&type))
  266. {
  267. PyErr_Clear();
  268. if (!PyArg_ParseTuple(args, "ss:settype", &path,&name)) return NULL;
  269. e=xosfscontrol_file_type_from_string(name,(bits*)&type);
  270. if(e) return riscos_oserror();
  271. }
  272. e=xosfile_set_type(path,type);
  273. if(e) return riscos_oserror();
  274. Py_INCREF(Py_None);
  275. return Py_None;
  276. }
  277. static PyObject *
  278. riscos_getenv(PyObject *self, PyObject *args)
  279. {
  280. char *name,*value;
  281. if(!PyArg_ParseTuple(args,"s:getenv",&name)) return NULL;
  282. value=getenv(name);
  283. if(value) return PyString_FromString(value);
  284. Py_INCREF(Py_None);
  285. return Py_None;
  286. }
  287. static PyObject *
  288. riscos_putenv(PyObject *self, PyObject *args)
  289. {
  290. char *name,*value;
  291. int len;
  292. os_var_type type=os_VARTYPE_LITERAL_STRING;
  293. if(!PyArg_ParseTuple(args,"ss|i:putenv",&name,&value,&type)) return NULL;
  294. if(type!=os_VARTYPE_STRING&&type!=os_VARTYPE_MACRO&&type!=os_VARTYPE_EXPANDED
  295. &&type!=os_VARTYPE_LITERAL_STRING)
  296. return riscos_error("Bad putenv type");
  297. len=strlen(value);
  298. if(type!=os_VARTYPE_LITERAL_STRING) len++;
  299. /* Other types need null terminator! */
  300. e=xos_set_var_val(name,(byte*)value,len,0,type,0,0);
  301. if(e) return riscos_oserror();
  302. Py_INCREF(Py_None);
  303. return Py_None;
  304. }
  305. static PyObject *
  306. riscos_delenv(PyObject *self, PyObject *args)
  307. {
  308. char *name;
  309. if(!PyArg_ParseTuple(args,"s:delenv",&name)) return NULL;
  310. e=xos_set_var_val(name,NULL,-1,0,0,0,0);
  311. if(e) return riscos_oserror();
  312. Py_INCREF(Py_None);
  313. return Py_None;
  314. }
  315. static PyObject *
  316. riscos_getenvdict(PyObject *self, PyObject *args)
  317. {
  318. PyObject *dict;
  319. char value[257];
  320. char *which="*";
  321. int size;
  322. char *context=NULL;
  323. if(!PyArg_ParseTuple(args,"|s:getenvdict",&which)) return NULL;
  324. dict = PyDict_New();
  325. if (!dict) return NULL;
  326. /* XXX This part ignores errors */
  327. while(!xos_read_var_val(which,value,sizeof(value)-1,(int)context,
  328. os_VARTYPE_EXPANDED,&size,(int *)&context,0))
  329. { PyObject *v;
  330. value[size]='\0';
  331. v = PyString_FromString(value);
  332. if (v == NULL) continue;
  333. PyDict_SetItemString(dict, context, v);
  334. Py_DECREF(v);
  335. }
  336. return dict;
  337. }
  338. static PyMethodDef riscos_methods[] = {
  339. {"unlink", riscos_remove, METH_VARARGS},
  340. {"remove", riscos_remove, METH_VARARGS},
  341. {"rename", riscos_rename, METH_VARARGS},
  342. {"system", riscos_system, METH_VARARGS},
  343. {"rmdir", riscos_remove, METH_VARARGS},
  344. {"chdir", riscos_chdir, METH_VARARGS},
  345. {"getcwd", riscos_getcwd, METH_NOARGS},
  346. {"expand", riscos_expand, METH_VARARGS},
  347. {"mkdir", riscos_mkdir, METH_VARARGS},
  348. {"listdir", riscos_listdir, METH_VARARGS},
  349. {"stat", riscos_stat, METH_VARARGS},
  350. {"lstat", riscos_stat, METH_VARARGS},
  351. {"chmod", riscos_chmod, METH_VARARGS},
  352. {"utime", riscos_utime, METH_VARARGS},
  353. {"settype", riscos_settype, METH_VARARGS},
  354. {"getenv", riscos_getenv, METH_VARARGS},
  355. {"putenv", riscos_putenv, METH_VARARGS},
  356. {"delenv", riscos_delenv, METH_VARARGS},
  357. {"getenvdict", riscos_getenvdict, METH_VARARGS},
  358. {NULL, NULL} /* Sentinel */
  359. };
  360. static int
  361. ins(PyObject *module, char *symbol, long value)
  362. {
  363. return PyModule_AddIntConstant(module, symbol, value);
  364. }
  365. static int
  366. all_ins(PyObject *d)
  367. {
  368. #ifdef F_OK
  369. if (ins(d, "F_OK", (long)F_OK)) return -1;
  370. #endif
  371. #ifdef R_OK
  372. if (ins(d, "R_OK", (long)R_OK)) return -1;
  373. #endif
  374. #ifdef W_OK
  375. if (ins(d, "W_OK", (long)W_OK)) return -1;
  376. #endif
  377. #ifdef X_OK
  378. if (ins(d, "X_OK", (long)X_OK)) return -1;
  379. #endif
  380. #ifdef NGROUPS_MAX
  381. if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
  382. #endif
  383. #ifdef TMP_MAX
  384. if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
  385. #endif
  386. #ifdef WCONTINUED
  387. if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
  388. #endif
  389. #ifdef WNOHANG
  390. if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
  391. #endif
  392. #ifdef WUNTRACED
  393. if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
  394. #endif
  395. #ifdef O_RDONLY
  396. if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
  397. #endif
  398. #ifdef O_WRONLY
  399. if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
  400. #endif
  401. #ifdef O_RDWR
  402. if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
  403. #endif
  404. #ifdef O_NDELAY
  405. if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
  406. #endif
  407. #ifdef O_NONBLOCK
  408. if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
  409. #endif
  410. #ifdef O_APPEND
  411. if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
  412. #endif
  413. #ifdef O_DSYNC
  414. if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
  415. #endif
  416. #ifdef O_RSYNC
  417. if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
  418. #endif
  419. #ifdef O_SYNC
  420. if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
  421. #endif
  422. #ifdef O_NOCTTY
  423. if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
  424. #endif
  425. #ifdef O_CREAT
  426. if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
  427. #endif
  428. #ifdef O_EXCL
  429. if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
  430. #endif
  431. #ifdef O_TRUNC
  432. if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
  433. #endif
  434. #ifdef O_BINARY
  435. if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
  436. #endif
  437. #ifdef O_TEXT
  438. if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
  439. #endif
  440. #ifdef O_LARGEFILE
  441. if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
  442. #endif
  443. /* MS Windows */
  444. #ifdef O_NOINHERIT
  445. /* Don't inherit in child processes. */
  446. if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
  447. #endif
  448. #ifdef _O_SHORT_LIVED
  449. /* Optimize for short life (keep in memory). */
  450. /* MS forgot to define this one with a non-underscore form too. */
  451. if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
  452. #endif
  453. #ifdef O_TEMPORARY
  454. /* Automatically delete when last handle is closed. */
  455. if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
  456. #endif
  457. #ifdef O_RANDOM
  458. /* Optimize for random access. */
  459. if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
  460. #endif
  461. #ifdef O_SEQUENTIAL
  462. /* Optimize for sequential access. */
  463. if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
  464. #endif
  465. /* GNU extensions. */
  466. #ifdef O_DIRECT
  467. /* Direct disk access. */
  468. if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
  469. #endif
  470. #ifdef O_DIRECTORY
  471. /* Must be a directory. */
  472. if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
  473. #endif
  474. #ifdef O_NOFOLLOW
  475. /* Do not follow links. */
  476. if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
  477. #endif
  478. /* These come from sysexits.h */
  479. #ifdef EX_OK
  480. if (ins(d, "EX_OK", (long)EX_OK)) return -1;
  481. #endif /* EX_OK */
  482. #ifdef EX_USAGE
  483. if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
  484. #endif /* EX_USAGE */
  485. #ifdef EX_DATAERR
  486. if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
  487. #endif /* EX_DATAERR */
  488. #ifdef EX_NOINPUT
  489. if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
  490. #endif /* EX_NOINPUT */
  491. #ifdef EX_NOUSER
  492. if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
  493. #endif /* EX_NOUSER */
  494. #ifdef EX_NOHOST
  495. if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
  496. #endif /* EX_NOHOST */
  497. #ifdef EX_UNAVAILABLE
  498. if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
  499. #endif /* EX_UNAVAILABLE */
  500. #ifdef EX_SOFTWARE
  501. if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
  502. #endif /* EX_SOFTWARE */
  503. #ifdef EX_OSERR
  504. if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
  505. #endif /* EX_OSERR */
  506. #ifdef EX_OSFILE
  507. if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
  508. #endif /* EX_OSFILE */
  509. #ifdef EX_CANTCREAT
  510. if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
  511. #endif /* EX_CANTCREAT */
  512. #ifdef EX_IOERR
  513. if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
  514. #endif /* EX_IOERR */
  515. #ifdef EX_TEMPFAIL
  516. if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
  517. #endif /* EX_TEMPFAIL */
  518. #ifdef EX_PROTOCOL
  519. if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
  520. #endif /* EX_PROTOCOL */
  521. #ifdef EX_NOPERM
  522. if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
  523. #endif /* EX_NOPERM */
  524. #ifdef EX_CONFIG
  525. if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
  526. #endif /* EX_CONFIG */
  527. #ifdef EX_NOTFOUND
  528. if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
  529. #endif /* EX_NOTFOUND */
  530. return 0;
  531. }
  532. void
  533. initriscos()
  534. {
  535. PyObject *m, *d, *stat_m;
  536. m = Py_InitModule("riscos", riscos_methods);
  537. if (all_ins(m))
  538. return;
  539. d = PyModule_GetDict(m);
  540. Py_INCREF(PyExc_OSError);
  541. PyModule_AddObject(m, "error", PyExc_OSError);
  542. PyStructSequence_InitType(&StatResultType, &stat_result_desc);
  543. PyDict_SetItemString(d, "stat_result", (PyObject*) &StatResultType);
  544. }