filesys.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573
  1. /* Copyright (C) 1996,1997,1998,1999,2000,2001,2004 Free Software Foundation, Inc.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. * Boston, MA 02110-1301 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice. */
  41. #include <stdio.h>
  42. #include <errno.h>
  43. #include "libguile/_scm.h"
  44. #include "libguile/smob.h"
  45. #include "libguile/feature.h"
  46. #include "libguile/fports.h"
  47. #include "libguile/iselect.h"
  48. #include "libguile/strings.h"
  49. #include "libguile/vectors.h"
  50. #include "libguile/validate.h"
  51. #include "libguile/filesys.h"
  52. #ifdef HAVE_IO_H
  53. #include <io.h>
  54. #endif
  55. #ifdef TIME_WITH_SYS_TIME
  56. # include <sys/time.h>
  57. # include <time.h>
  58. #else
  59. # if HAVE_SYS_TIME_H
  60. # include <sys/time.h>
  61. # else
  62. # include <time.h>
  63. # endif
  64. #endif
  65. #ifdef HAVE_UNISTD_H
  66. #include <unistd.h>
  67. #endif
  68. #ifdef LIBC_H_WITH_UNISTD_H
  69. #include <libc.h>
  70. #endif
  71. #ifdef HAVE_SYS_SELECT_H
  72. #include <sys/select.h>
  73. #endif
  74. #ifdef HAVE_STRING_H
  75. #include <string.h>
  76. #endif
  77. #include <sys/types.h>
  78. #include <sys/stat.h>
  79. #include <fcntl.h>
  80. #ifdef HAVE_PWD_H
  81. #include <pwd.h>
  82. #endif
  83. #if HAVE_DIRENT_H
  84. # include <dirent.h>
  85. # define NAMLEN(dirent) strlen((dirent)->d_name)
  86. #else
  87. # define dirent direct
  88. # define NAMLEN(dirent) (dirent)->d_namlen
  89. # if HAVE_SYS_NDIR_H
  90. # include <sys/ndir.h>
  91. # endif
  92. # if HAVE_SYS_DIR_H
  93. # include <sys/dir.h>
  94. # endif
  95. # if HAVE_NDIR_H
  96. # include <ndir.h>
  97. # endif
  98. #endif
  99. /* Ultrix has S_IFSOCK, but no S_ISSOCK. Ipe! */
  100. #if defined (S_IFSOCK) && ! defined (S_ISSOCK)
  101. #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
  102. #endif
  103. /* The MinGW gcc does not define the S_ISSOCK macro. Any other native Windows
  104. compiler like BorlandC or MSVC has none of these macros defined. */
  105. #ifdef __MINGW32__
  106. # define S_ISSOCK(mode) (0)
  107. #endif
  108. #if defined (__BORLANDC__) || defined (_MSC_VER)
  109. # define S_ISBLK(mode) (0)
  110. # define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
  111. # define S_ISCHR(mode) (((mode) & _S_IFMT) == _S_IFCHR)
  112. # define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR)
  113. # define S_ISREG(mode) (((mode) & _S_IFMT) == _S_IFREG)
  114. #endif
  115. /* Some more definitions for the native Windows port. */
  116. #ifdef __MINGW32__
  117. # define mkdir(path, mode) mkdir (path)
  118. # define fsync(fd) _commit (fd)
  119. # define fchmod(fd, mode) (-1)
  120. #endif /* __MINGW32__ */
  121. /* {Permissions}
  122. */
  123. #ifdef HAVE_CHOWN
  124. SCM_DEFINE (scm_chown, "chown", 3, 0, 0,
  125. (SCM object, SCM owner, SCM group),
  126. "Change the ownership and group of the file referred to by @var{object} to\n"
  127. "the integer values @var{owner} and @var{group}. @var{object} can be\n"
  128. "a string containing a file name or, if the platform\n"
  129. "supports fchown, a port or integer file descriptor\n"
  130. "which is open on the file. The return value\n"
  131. "is unspecified.\n\n"
  132. "If @var{object} is a symbolic link, either the\n"
  133. "ownership of the link or the ownership of the referenced file will be\n"
  134. "changed depending on the operating system (lchown is\n"
  135. "unsupported at present). If @var{owner} or @var{group} is specified\n"
  136. "as @code{-1}, then that ID is not changed.")
  137. #define FUNC_NAME s_scm_chown
  138. {
  139. int rv;
  140. object = SCM_COERCE_OUTPORT (object);
  141. SCM_VALIDATE_INUM (2,owner);
  142. SCM_VALIDATE_INUM (3,group);
  143. #ifdef HAVE_FCHOWN
  144. if (SCM_INUMP (object) || (SCM_OPFPORTP (object)))
  145. {
  146. int fdes = SCM_INUMP (object) ? SCM_INUM (object)
  147. : SCM_FPORT_FDES (object);
  148. SCM_SYSCALL (rv = fchown (fdes, SCM_INUM (owner), SCM_INUM (group)));
  149. }
  150. else
  151. #endif
  152. {
  153. SCM_VALIDATE_STRING (1, object);
  154. SCM_STRING_COERCE_0TERMINATION_X (object);
  155. SCM_SYSCALL (rv = chown (SCM_STRING_CHARS (object),
  156. SCM_INUM (owner), SCM_INUM (group)));
  157. }
  158. if (rv == -1)
  159. SCM_SYSERROR;
  160. return SCM_UNSPECIFIED;
  161. }
  162. #undef FUNC_NAME
  163. #endif /* HAVE_CHOWN */
  164. SCM_DEFINE (scm_chmod, "chmod", 2, 0, 0,
  165. (SCM object, SCM mode),
  166. "Changes the permissions of the file referred to by @var{obj}.\n"
  167. "@var{obj} can be a string containing a file name or a port or integer file\n"
  168. "descriptor which is open on a file (in which case @code{fchmod} is used\n"
  169. "as the underlying system call).\n"
  170. "@var{mode} specifies\n"
  171. "the new permissions as a decimal number, e.g., @code{(chmod \"foo\" #o755)}.\n"
  172. "The return value is unspecified.")
  173. #define FUNC_NAME s_scm_chmod
  174. {
  175. int rv;
  176. int fdes;
  177. object = SCM_COERCE_OUTPORT (object);
  178. SCM_VALIDATE_INUM (2,mode);
  179. if (SCM_INUMP (object) || SCM_OPFPORTP (object))
  180. {
  181. if (SCM_INUMP (object))
  182. fdes = SCM_INUM (object);
  183. else
  184. fdes = SCM_FPORT_FDES (object);
  185. SCM_SYSCALL (rv = fchmod (fdes, SCM_INUM (mode)));
  186. }
  187. else
  188. {
  189. SCM_VALIDATE_STRING (1, object);
  190. SCM_STRING_COERCE_0TERMINATION_X (object);
  191. SCM_SYSCALL (rv = chmod (SCM_STRING_CHARS (object), SCM_INUM (mode)));
  192. }
  193. if (rv == -1)
  194. SCM_SYSERROR;
  195. return SCM_UNSPECIFIED;
  196. }
  197. #undef FUNC_NAME
  198. SCM_DEFINE (scm_umask, "umask", 0, 1, 0,
  199. (SCM mode),
  200. "If @var{mode} is omitted, returns a decimal number representing the current\n"
  201. "file creation mask. Otherwise the file creation mask is set to\n"
  202. "@var{mode} and the previous value is returned.\n\n"
  203. "E.g., @code{(umask #o022)} sets the mask to octal 22, decimal 18.")
  204. #define FUNC_NAME s_scm_umask
  205. {
  206. mode_t mask;
  207. if (SCM_UNBNDP (mode))
  208. {
  209. mask = umask (0);
  210. umask (mask);
  211. }
  212. else
  213. {
  214. SCM_VALIDATE_INUM (1,mode);
  215. mask = umask (SCM_INUM (mode));
  216. }
  217. return SCM_MAKINUM (mask);
  218. }
  219. #undef FUNC_NAME
  220. SCM_DEFINE (scm_open_fdes, "open-fdes", 2, 1, 0,
  221. (SCM path, SCM flags, SCM mode),
  222. "Similar to @code{open} but return a file descriptor instead of\n"
  223. "a port.")
  224. #define FUNC_NAME s_scm_open_fdes
  225. {
  226. int fd;
  227. int iflags;
  228. int imode;
  229. SCM_VALIDATE_STRING (1, path);
  230. SCM_STRING_COERCE_0TERMINATION_X (path);
  231. iflags = SCM_NUM2INT (2, flags);
  232. imode = SCM_NUM2INT_DEF (3, mode, 0666);
  233. SCM_SYSCALL (fd = open (SCM_STRING_CHARS (path), iflags, imode));
  234. if (fd == -1)
  235. SCM_SYSERROR;
  236. return SCM_MAKINUM (fd);
  237. }
  238. #undef FUNC_NAME
  239. SCM_DEFINE (scm_open, "open", 2, 1, 0,
  240. (SCM path, SCM flags, SCM mode),
  241. "Open the file named by @var{path} for reading and/or writing.\n"
  242. "@var{flags} is an integer specifying how the file should be opened.\n"
  243. "@var{mode} is an integer specifying the permission bits of the file, if\n"
  244. "it needs to be created, before the umask is applied. The default is 666\n"
  245. "(Unix itself has no default).\n\n"
  246. "@var{flags} can be constructed by combining variables using @code{logior}.\n"
  247. "Basic flags are:\n\n"
  248. "@defvar O_RDONLY\n"
  249. "Open the file read-only.\n"
  250. "@end defvar\n"
  251. "@defvar O_WRONLY\n"
  252. "Open the file write-only.\n"
  253. "@end defvar\n"
  254. "@defvar O_RDWR\n"
  255. "Open the file read/write.\n"
  256. "@end defvar\n"
  257. "@defvar O_APPEND\n"
  258. "Append to the file instead of truncating.\n"
  259. "@end defvar\n"
  260. "@defvar O_CREAT\n"
  261. "Create the file if it does not already exist.\n"
  262. "@end defvar\n\n"
  263. "See the Unix documentation of the @code{open} system call\n"
  264. "for additional flags.")
  265. #define FUNC_NAME s_scm_open
  266. {
  267. SCM newpt;
  268. char *port_mode;
  269. int fd;
  270. int iflags;
  271. fd = SCM_INUM (scm_open_fdes (path, flags, mode));
  272. iflags = SCM_NUM2INT (2, flags);
  273. if (iflags & O_RDWR)
  274. {
  275. if (iflags & O_APPEND)
  276. port_mode = "a+";
  277. else if (iflags & O_CREAT)
  278. port_mode = "w+";
  279. else
  280. port_mode = "r+";
  281. }
  282. else {
  283. if (iflags & O_APPEND)
  284. port_mode = "a";
  285. else if (iflags & O_WRONLY)
  286. port_mode = "w";
  287. else
  288. port_mode = "r";
  289. }
  290. newpt = scm_fdes_to_port (fd, port_mode, path);
  291. return newpt;
  292. }
  293. #undef FUNC_NAME
  294. SCM_DEFINE (scm_close, "close", 1, 0, 0,
  295. (SCM fd_or_port),
  296. "Similar to close-port (@pxref{Closing, close-port}),\n"
  297. "but also works on file descriptors. A side\n"
  298. "effect of closing a file descriptor is that any ports using that file\n"
  299. "descriptor are moved to a different file descriptor and have\n"
  300. "their revealed counts set to zero.")
  301. #define FUNC_NAME s_scm_close
  302. {
  303. int rv;
  304. int fd;
  305. fd_or_port = SCM_COERCE_OUTPORT (fd_or_port);
  306. if (SCM_PORTP (fd_or_port))
  307. return scm_close_port (fd_or_port);
  308. SCM_VALIDATE_INUM (1,fd_or_port);
  309. fd = SCM_INUM (fd_or_port);
  310. scm_evict_ports (fd); /* see scsh manual. */
  311. SCM_SYSCALL (rv = close (fd));
  312. /* following scsh, closing an already closed file descriptor is
  313. not an error. */
  314. if (rv < 0 && errno != EBADF)
  315. SCM_SYSERROR;
  316. return SCM_BOOL (rv >= 0);
  317. }
  318. #undef FUNC_NAME
  319. SCM_DEFINE (scm_close_fdes, "close-fdes", 1, 0, 0,
  320. (SCM fd),
  321. "A simple wrapper for the @code{close} system call.\n"
  322. "Close file descriptor @var{fd}, which must be an integer.\n"
  323. "Unlike close (@pxref{Ports and File Descriptors, close}),\n"
  324. "the file descriptor will be closed even if a port is using it.\n"
  325. "The return value is unspecified.")
  326. #define FUNC_NAME s_scm_close_fdes
  327. {
  328. int c_fd;
  329. int rv;
  330. SCM_VALIDATE_INUM_COPY (1, fd, c_fd);
  331. SCM_SYSCALL (rv = close (c_fd));
  332. if (rv < 0)
  333. SCM_SYSERROR;
  334. return SCM_UNSPECIFIED;
  335. }
  336. #undef FUNC_NAME
  337. /* {Files}
  338. */
  339. SCM_SYMBOL (scm_sym_regular, "regular");
  340. SCM_SYMBOL (scm_sym_directory, "directory");
  341. #ifdef HAVE_S_ISLNK
  342. SCM_SYMBOL (scm_sym_symlink, "symlink");
  343. #endif
  344. SCM_SYMBOL (scm_sym_block_special, "block-special");
  345. SCM_SYMBOL (scm_sym_char_special, "char-special");
  346. SCM_SYMBOL (scm_sym_fifo, "fifo");
  347. SCM_SYMBOL (scm_sym_sock, "socket");
  348. SCM_SYMBOL (scm_sym_unknown, "unknown");
  349. static SCM
  350. scm_stat2scm (struct stat *stat_temp)
  351. {
  352. SCM ans = scm_c_make_vector (15, SCM_UNSPECIFIED);
  353. SCM *ve = SCM_VELTS (ans);
  354. ve[0] = scm_ulong2num ((unsigned long) stat_temp->st_dev);
  355. ve[1] = scm_ulong2num ((unsigned long) stat_temp->st_ino);
  356. ve[2] = scm_ulong2num ((unsigned long) stat_temp->st_mode);
  357. ve[3] = scm_ulong2num ((unsigned long) stat_temp->st_nlink);
  358. ve[4] = scm_ulong2num ((unsigned long) stat_temp->st_uid);
  359. ve[5] = scm_ulong2num ((unsigned long) stat_temp->st_gid);
  360. #ifdef HAVE_STRUCT_STAT_ST_RDEV
  361. ve[6] = scm_ulong2num ((unsigned long) stat_temp->st_rdev);
  362. #else
  363. ve[6] = SCM_BOOL_F;
  364. #endif
  365. ve[7] = scm_ulong2num ((unsigned long) stat_temp->st_size);
  366. ve[8] = scm_ulong2num ((unsigned long) stat_temp->st_atime);
  367. ve[9] = scm_ulong2num ((unsigned long) stat_temp->st_mtime);
  368. ve[10] = scm_ulong2num ((unsigned long) stat_temp->st_ctime);
  369. #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  370. ve[11] = scm_ulong2num ((unsigned long) stat_temp->st_blksize);
  371. #else
  372. ve[11] = scm_ulong2num (4096L);
  373. #endif
  374. #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
  375. ve[12] = scm_ulong2num ((unsigned long) stat_temp->st_blocks);
  376. #else
  377. ve[12] = SCM_BOOL_F;
  378. #endif
  379. {
  380. int mode = stat_temp->st_mode;
  381. if (S_ISREG (mode))
  382. ve[13] = scm_sym_regular;
  383. else if (S_ISDIR (mode))
  384. ve[13] = scm_sym_directory;
  385. #ifdef HAVE_S_ISLNK
  386. else if (S_ISLNK (mode))
  387. ve[13] = scm_sym_symlink;
  388. #endif
  389. else if (S_ISBLK (mode))
  390. ve[13] = scm_sym_block_special;
  391. else if (S_ISCHR (mode))
  392. ve[13] = scm_sym_char_special;
  393. else if (S_ISFIFO (mode))
  394. ve[13] = scm_sym_fifo;
  395. #ifdef S_ISSOCK
  396. else if (S_ISSOCK (mode))
  397. ve[13] = scm_sym_sock;
  398. #endif
  399. else
  400. ve[13] = scm_sym_unknown;
  401. ve[14] = SCM_MAKINUM ((~S_IFMT) & mode);
  402. /* the layout of the bits in ve[14] is intended to be portable.
  403. If there are systems that don't follow the usual convention,
  404. the following could be used:
  405. tmp = 0;
  406. if (S_ISUID & mode) tmp += 1;
  407. tmp <<= 1;
  408. if (S_IRGRP & mode) tmp += 1;
  409. tmp <<= 1;
  410. if (S_ISVTX & mode) tmp += 1;
  411. tmp <<= 1;
  412. if (S_IRUSR & mode) tmp += 1;
  413. tmp <<= 1;
  414. if (S_IWUSR & mode) tmp += 1;
  415. tmp <<= 1;
  416. if (S_IXUSR & mode) tmp += 1;
  417. tmp <<= 1;
  418. if (S_IWGRP & mode) tmp += 1;
  419. tmp <<= 1;
  420. if (S_IXGRP & mode) tmp += 1;
  421. tmp <<= 1;
  422. if (S_IROTH & mode) tmp += 1;
  423. tmp <<= 1;
  424. if (S_IWOTH & mode) tmp += 1;
  425. tmp <<= 1;
  426. if (S_IXOTH & mode) tmp += 1;
  427. ve[14] = SCM_MAKINUM (tmp);
  428. */
  429. }
  430. return ans;
  431. }
  432. SCM_DEFINE (scm_stat, "stat", 1, 0, 0,
  433. (SCM object),
  434. "Return an object containing various information about the file\n"
  435. "determined by @var{obj}. @var{obj} can be a string containing\n"
  436. "a file name or a port or integer file descriptor which is open\n"
  437. "on a file (in which case @code{fstat} is used as the underlying\n"
  438. "system call).\n"
  439. "\n"
  440. "The object returned by @code{stat} can be passed as a single\n"
  441. "parameter to the following procedures, all of which return\n"
  442. "integers:\n"
  443. "\n"
  444. "@table @code\n"
  445. "@item stat:dev\n"
  446. "The device containing the file.\n"
  447. "@item stat:ino\n"
  448. "The file serial number, which distinguishes this file from all\n"
  449. "other files on the same device.\n"
  450. "@item stat:mode\n"
  451. "The mode of the file. This includes file type information and\n"
  452. "the file permission bits. See @code{stat:type} and\n"
  453. "@code{stat:perms} below.\n"
  454. "@item stat:nlink\n"
  455. "The number of hard links to the file.\n"
  456. "@item stat:uid\n"
  457. "The user ID of the file's owner.\n"
  458. "@item stat:gid\n"
  459. "The group ID of the file.\n"
  460. "@item stat:rdev\n"
  461. "Device ID; this entry is defined only for character or block\n"
  462. "special files.\n"
  463. "@item stat:size\n"
  464. "The size of a regular file in bytes.\n"
  465. "@item stat:atime\n"
  466. "The last access time for the file.\n"
  467. "@item stat:mtime\n"
  468. "The last modification time for the file.\n"
  469. "@item stat:ctime\n"
  470. "The last modification time for the attributes of the file.\n"
  471. "@item stat:blksize\n"
  472. "The optimal block size for reading or writing the file, in\n"
  473. "bytes.\n"
  474. "@item stat:blocks\n"
  475. "The amount of disk space that the file occupies measured in\n"
  476. "units of 512 byte blocks.\n"
  477. "@end table\n"
  478. "\n"
  479. "In addition, the following procedures return the information\n"
  480. "from stat:mode in a more convenient form:\n"
  481. "\n"
  482. "@table @code\n"
  483. "@item stat:type\n"
  484. "A symbol representing the type of file. Possible values are\n"
  485. "regular, directory, symlink, block-special, char-special, fifo,\n"
  486. "socket and unknown\n"
  487. "@item stat:perms\n"
  488. "An integer representing the access permission bits.\n"
  489. "@end table")
  490. #define FUNC_NAME s_scm_stat
  491. {
  492. int rv;
  493. int fdes;
  494. struct stat stat_temp;
  495. if (SCM_INUMP (object))
  496. {
  497. SCM_SYSCALL (rv = fstat (SCM_INUM (object), &stat_temp));
  498. }
  499. else if (SCM_STRINGP (object))
  500. {
  501. SCM_STRING_COERCE_0TERMINATION_X (object);
  502. SCM_SYSCALL (rv = stat (SCM_STRING_CHARS (object), &stat_temp));
  503. }
  504. else
  505. {
  506. object = SCM_COERCE_OUTPORT (object);
  507. SCM_VALIDATE_OPFPORT (1, object);
  508. fdes = SCM_FPORT_FDES (object);
  509. SCM_SYSCALL (rv = fstat (fdes, &stat_temp));
  510. }
  511. if (rv == -1)
  512. {
  513. int en = errno;
  514. SCM_SYSERROR_MSG ("~A: ~S",
  515. scm_list_2 (scm_makfrom0str (strerror (errno)),
  516. object),
  517. en);
  518. }
  519. return scm_stat2scm (&stat_temp);
  520. }
  521. #undef FUNC_NAME
  522. /* {Modifying Directories}
  523. */
  524. #ifdef HAVE_LINK
  525. SCM_DEFINE (scm_link, "link", 2, 0, 0,
  526. (SCM oldpath, SCM newpath),
  527. "Creates a new name @var{newpath} in the file system for the\n"
  528. "file named by @var{oldpath}. If @var{oldpath} is a symbolic\n"
  529. "link, the link may or may not be followed depending on the\n"
  530. "system.")
  531. #define FUNC_NAME s_scm_link
  532. {
  533. int val;
  534. SCM_VALIDATE_STRING (1, oldpath);
  535. SCM_STRING_COERCE_0TERMINATION_X (oldpath);
  536. SCM_VALIDATE_STRING (2, newpath);
  537. SCM_STRING_COERCE_0TERMINATION_X (newpath);
  538. SCM_SYSCALL (val = link (SCM_STRING_CHARS (oldpath),
  539. SCM_STRING_CHARS (newpath)));
  540. if (val != 0)
  541. SCM_SYSERROR;
  542. return SCM_UNSPECIFIED;
  543. }
  544. #undef FUNC_NAME
  545. #endif /* HAVE_LINK */
  546. SCM_DEFINE (scm_rename, "rename-file", 2, 0, 0,
  547. (SCM oldname, SCM newname),
  548. "Renames the file specified by @var{oldname} to @var{newname}.\n"
  549. "The return value is unspecified.")
  550. #define FUNC_NAME s_scm_rename
  551. {
  552. int rv;
  553. SCM_VALIDATE_STRING (1, oldname);
  554. SCM_VALIDATE_STRING (2, newname);
  555. SCM_STRING_COERCE_0TERMINATION_X (oldname);
  556. SCM_STRING_COERCE_0TERMINATION_X (newname);
  557. #ifdef HAVE_RENAME
  558. SCM_SYSCALL (rv = rename (SCM_STRING_CHARS (oldname), SCM_STRING_CHARS (newname)));
  559. #else
  560. SCM_SYSCALL (rv = link (SCM_STRING_CHARS (oldname), SCM_STRING_CHARS (newname)));
  561. if (rv == 0)
  562. {
  563. SCM_SYSCALL (rv = unlink (SCM_STRING_CHARS (oldname)));;
  564. if (rv != 0)
  565. /* unlink failed. remove new name */
  566. SCM_SYSCALL (unlink (SCM_STRING_CHARS (newname)));
  567. }
  568. #endif
  569. if (rv != 0)
  570. SCM_SYSERROR;
  571. return SCM_UNSPECIFIED;
  572. }
  573. #undef FUNC_NAME
  574. SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0,
  575. (SCM str),
  576. "Deletes (or \"unlinks\") the file specified by @var{path}.")
  577. #define FUNC_NAME s_scm_delete_file
  578. {
  579. int ans;
  580. SCM_VALIDATE_STRING (1, str);
  581. SCM_STRING_COERCE_0TERMINATION_X (str);
  582. SCM_SYSCALL (ans = unlink (SCM_STRING_CHARS (str)));
  583. if (ans != 0)
  584. SCM_SYSERROR;
  585. return SCM_UNSPECIFIED;
  586. }
  587. #undef FUNC_NAME
  588. #ifdef HAVE_MKDIR
  589. SCM_DEFINE (scm_mkdir, "mkdir", 1, 1, 0,
  590. (SCM path, SCM mode),
  591. "Create a new directory named by @var{path}. If @var{mode} is omitted\n"
  592. "then the permissions of the directory file are set using the current\n"
  593. "umask. Otherwise they are set to the decimal value specified with\n"
  594. "@var{mode}. The return value is unspecified.")
  595. #define FUNC_NAME s_scm_mkdir
  596. {
  597. int rv;
  598. mode_t mask;
  599. SCM_VALIDATE_STRING (1, path);
  600. SCM_STRING_COERCE_0TERMINATION_X (path);
  601. if (SCM_UNBNDP (mode))
  602. {
  603. mask = umask (0);
  604. umask (mask);
  605. SCM_SYSCALL (rv = mkdir (SCM_STRING_CHARS (path), 0777 ^ mask));
  606. }
  607. else
  608. {
  609. SCM_VALIDATE_INUM (2,mode);
  610. SCM_SYSCALL (rv = mkdir (SCM_STRING_CHARS (path), SCM_INUM (mode)));
  611. }
  612. if (rv != 0)
  613. SCM_SYSERROR;
  614. return SCM_UNSPECIFIED;
  615. }
  616. #undef FUNC_NAME
  617. #endif /* HAVE_MKDIR */
  618. #ifdef HAVE_RMDIR
  619. SCM_DEFINE (scm_rmdir, "rmdir", 1, 0, 0,
  620. (SCM path),
  621. "Remove the existing directory named by @var{path}. The directory must\n"
  622. "be empty for this to succeed. The return value is unspecified.")
  623. #define FUNC_NAME s_scm_rmdir
  624. {
  625. int val;
  626. SCM_VALIDATE_STRING (1, path);
  627. SCM_STRING_COERCE_0TERMINATION_X (path);
  628. SCM_SYSCALL (val = rmdir (SCM_STRING_CHARS (path)));
  629. if (val != 0)
  630. SCM_SYSERROR;
  631. return SCM_UNSPECIFIED;
  632. }
  633. #undef FUNC_NAME
  634. #endif
  635. /* {Examining Directories}
  636. */
  637. scm_t_bits scm_tc16_dir;
  638. SCM_DEFINE (scm_directory_stream_p, "directory-stream?", 1, 0, 0,
  639. (SCM obj),
  640. "Return a boolean indicating whether @var{object} is a directory\n"
  641. "stream as returned by @code{opendir}.")
  642. #define FUNC_NAME s_scm_directory_stream_p
  643. {
  644. return SCM_BOOL (SCM_DIRP (obj));
  645. }
  646. #undef FUNC_NAME
  647. SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
  648. (SCM dirname),
  649. "Open the directory specified by @var{path} and return a directory\n"
  650. "stream.")
  651. #define FUNC_NAME s_scm_opendir
  652. {
  653. DIR *ds;
  654. SCM_VALIDATE_STRING (1, dirname);
  655. SCM_STRING_COERCE_0TERMINATION_X (dirname);
  656. SCM_SYSCALL (ds = opendir (SCM_STRING_CHARS (dirname)));
  657. if (ds == NULL)
  658. SCM_SYSERROR;
  659. SCM_RETURN_NEWSMOB (scm_tc16_dir | SCM_DIR_FLAG_OPEN, ds);
  660. }
  661. #undef FUNC_NAME
  662. SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
  663. (SCM port),
  664. "Return (as a string) the next directory entry from the directory stream\n"
  665. "@var{stream}. If there is no remaining entry to be read then the\n"
  666. "end of file object is returned.")
  667. #define FUNC_NAME s_scm_readdir
  668. {
  669. struct dirent *rdent;
  670. SCM_VALIDATE_DIR (1, port);
  671. if (!SCM_DIR_OPEN_P (port))
  672. SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
  673. errno = 0;
  674. SCM_SYSCALL (rdent = readdir ((DIR *) SCM_CELL_WORD_1 (port)));
  675. if (errno != 0)
  676. SCM_SYSERROR;
  677. return (rdent ? scm_mem2string (rdent->d_name, NAMLEN (rdent))
  678. : SCM_EOF_VAL);
  679. }
  680. #undef FUNC_NAME
  681. SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0,
  682. (SCM port),
  683. "Reset the directory port @var{stream} so that the next call to\n"
  684. "@code{readdir} will return the first directory entry.")
  685. #define FUNC_NAME s_scm_rewinddir
  686. {
  687. SCM_VALIDATE_DIR (1, port);
  688. if (!SCM_DIR_OPEN_P (port))
  689. SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
  690. rewinddir ((DIR *) SCM_CELL_WORD_1 (port));
  691. return SCM_UNSPECIFIED;
  692. }
  693. #undef FUNC_NAME
  694. SCM_DEFINE (scm_closedir, "closedir", 1, 0, 0,
  695. (SCM port),
  696. "Close the directory stream @var{stream}.\n"
  697. "The return value is unspecified.")
  698. #define FUNC_NAME s_scm_closedir
  699. {
  700. SCM_VALIDATE_DIR (1, port);
  701. if (SCM_DIR_OPEN_P (port))
  702. {
  703. int sts;
  704. SCM_SYSCALL (sts = closedir ((DIR *) SCM_CELL_WORD_1 (port)));
  705. if (sts != 0)
  706. SCM_SYSERROR;
  707. SCM_SET_CELL_WORD_0 (port, scm_tc16_dir);
  708. }
  709. return SCM_UNSPECIFIED;
  710. }
  711. #undef FUNC_NAME
  712. static int
  713. scm_dir_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
  714. {
  715. scm_puts ("#<", port);
  716. if (!SCM_DIR_OPEN_P (exp))
  717. scm_puts ("closed: ", port);
  718. scm_puts ("directory stream ", port);
  719. scm_intprint (SCM_CELL_WORD_1 (exp), 16, port);
  720. scm_putc ('>', port);
  721. return 1;
  722. }
  723. static size_t
  724. scm_dir_free (SCM p)
  725. {
  726. if (SCM_DIR_OPEN_P (p))
  727. closedir ((DIR *) SCM_CELL_WORD_1 (p));
  728. return 0;
  729. }
  730. /* {Navigating Directories}
  731. */
  732. SCM_DEFINE (scm_chdir, "chdir", 1, 0, 0,
  733. (SCM str),
  734. "Change the current working directory to @var{path}.\n"
  735. "The return value is unspecified.")
  736. #define FUNC_NAME s_scm_chdir
  737. {
  738. int ans;
  739. SCM_VALIDATE_STRING (1, str);
  740. SCM_STRING_COERCE_0TERMINATION_X (str);
  741. SCM_SYSCALL (ans = chdir (SCM_STRING_CHARS (str)));
  742. if (ans != 0)
  743. SCM_SYSERROR;
  744. return SCM_UNSPECIFIED;
  745. }
  746. #undef FUNC_NAME
  747. #ifdef HAVE_GETCWD
  748. SCM_DEFINE (scm_getcwd, "getcwd", 0, 0, 0,
  749. (),
  750. "Return the name of the current working directory.")
  751. #define FUNC_NAME s_scm_getcwd
  752. {
  753. char *rv;
  754. size_t size = 100;
  755. char *wd;
  756. SCM result;
  757. wd = scm_must_malloc (size, FUNC_NAME);
  758. while ((rv = getcwd (wd, size)) == 0 && errno == ERANGE)
  759. {
  760. scm_must_free (wd);
  761. size *= 2;
  762. wd = scm_must_malloc (size, FUNC_NAME);
  763. }
  764. if (rv == 0)
  765. {
  766. int save_errno = errno;
  767. free (wd);
  768. errno = save_errno;
  769. SCM_SYSERROR;
  770. }
  771. result = scm_mem2string (wd, strlen (wd));
  772. scm_must_free (wd);
  773. return result;
  774. }
  775. #undef FUNC_NAME
  776. #endif /* HAVE_GETCWD */
  777. #ifdef HAVE_SELECT
  778. /* check that element is a port or file descriptor. if it's a port
  779. and its buffer is ready for use, add it to the ports_ready list.
  780. otherwise add its file descriptor to *set. the type of list can be
  781. determined from pos: SCM_ARG1 for reads, SCM_ARG2 for writes,
  782. SCM_ARG3 for excepts. */
  783. static int
  784. set_element (SELECT_TYPE *set, SCM *ports_ready, SCM element, int pos)
  785. {
  786. int fd;
  787. if (SCM_INUMP (element))
  788. {
  789. fd = SCM_INUM (element);
  790. }
  791. else
  792. {
  793. int use_buf = 0;
  794. element = SCM_COERCE_OUTPORT (element);
  795. SCM_ASSERT (SCM_OPFPORTP (element), element, pos, "select");
  796. if (pos == SCM_ARG1)
  797. {
  798. /* check whether port has buffered input. */
  799. scm_t_port *pt = SCM_PTAB_ENTRY (element);
  800. if (pt->read_pos < pt->read_end)
  801. use_buf = 1;
  802. }
  803. else if (pos == SCM_ARG2)
  804. {
  805. /* check whether port's output buffer has room. */
  806. scm_t_port *pt = SCM_PTAB_ENTRY (element);
  807. /* > 1 since writing the last byte in the buffer causes flush. */
  808. if (pt->write_end - pt->write_pos > 1)
  809. use_buf = 1;
  810. }
  811. fd = use_buf ? -1 : SCM_FPORT_FDES (element);
  812. }
  813. if (fd == -1)
  814. *ports_ready = scm_cons (element, *ports_ready);
  815. else
  816. FD_SET (fd, set);
  817. return fd;
  818. }
  819. /* check list_or_vec, a list or vector of ports or file descriptors,
  820. adding each member to either the ports_ready list (if it's a port
  821. with a usable buffer) or to *set. the kind of list_or_vec can be
  822. determined from pos: SCM_ARG1 for reads, SCM_ARG2 for writes,
  823. SCM_ARG3 for excepts. */
  824. static int
  825. fill_select_type (SELECT_TYPE *set, SCM *ports_ready, SCM list_or_vec, int pos)
  826. {
  827. int max_fd = 0;
  828. if (SCM_VECTORP (list_or_vec))
  829. {
  830. int i = SCM_VECTOR_LENGTH (list_or_vec);
  831. SCM *ve = SCM_VELTS (list_or_vec);
  832. while (--i >= 0)
  833. {
  834. int fd = set_element (set, ports_ready, ve[i], pos);
  835. if (fd > max_fd)
  836. max_fd = fd;
  837. }
  838. }
  839. else
  840. {
  841. while (!SCM_NULLP (list_or_vec))
  842. {
  843. int fd = set_element (set, ports_ready, SCM_CAR (list_or_vec), pos);
  844. if (fd > max_fd)
  845. max_fd = fd;
  846. list_or_vec = SCM_CDR (list_or_vec);
  847. }
  848. }
  849. return max_fd;
  850. }
  851. /* if element (a file descriptor or port) appears in *set, cons it to
  852. list. return list. */
  853. static SCM
  854. get_element (SELECT_TYPE *set, SCM element, SCM list)
  855. {
  856. int fd;
  857. if (SCM_INUMP (element))
  858. {
  859. fd = SCM_INUM (element);
  860. }
  861. else
  862. {
  863. fd = SCM_FPORT_FDES (SCM_COERCE_OUTPORT (element));
  864. }
  865. if (FD_ISSET (fd, set))
  866. list = scm_cons (element, list);
  867. return list;
  868. }
  869. /* construct component of scm_select return value.
  870. set: pointer to set of file descriptors found by select to be ready
  871. ports_ready: ports ready due to buffering
  872. list_or_vec: original list/vector handed to scm_select.
  873. the return value is a list/vector of ready ports/file descriptors.
  874. works by finding the objects in list which correspond to members of
  875. *set and appending them to ports_ready. result is converted to a
  876. vector if list_or_vec is a vector. */
  877. static SCM
  878. retrieve_select_type (SELECT_TYPE *set, SCM ports_ready, SCM list_or_vec)
  879. {
  880. SCM answer_list = ports_ready;
  881. if (SCM_VECTORP (list_or_vec))
  882. {
  883. int i = SCM_VECTOR_LENGTH (list_or_vec);
  884. SCM *ve = SCM_VELTS (list_or_vec);
  885. while (--i >= 0)
  886. {
  887. answer_list = get_element (set, ve[i], answer_list);
  888. }
  889. return scm_vector (answer_list);
  890. }
  891. else
  892. {
  893. /* list_or_vec must be a list. */
  894. while (!SCM_NULLP (list_or_vec))
  895. {
  896. answer_list = get_element (set, SCM_CAR (list_or_vec), answer_list);
  897. list_or_vec = SCM_CDR (list_or_vec);
  898. }
  899. return answer_list;
  900. }
  901. }
  902. /* Static helper functions above refer to s_scm_select directly as s_select */
  903. SCM_DEFINE (scm_select, "select", 3, 2, 0,
  904. (SCM reads, SCM writes, SCM excepts, SCM secs, SCM usecs),
  905. "This procedure has a variety of uses: waiting for the ability\n"
  906. "to provide input, accept output, or the existence of\n"
  907. "exceptional conditions on a collection of ports or file\n"
  908. "descriptors, or waiting for a timeout to occur.\n"
  909. "It also returns if interrupted by a signal.\n\n"
  910. "@var{reads}, @var{writes} and @var{excepts} can be lists or\n"
  911. "vectors, with each member a port or a file descriptor.\n"
  912. "The value returned is a list of three corresponding\n"
  913. "lists or vectors containing only the members which meet the\n"
  914. "specified requirement. The ability of port buffers to\n"
  915. "provide input or accept output is taken into account.\n"
  916. "Ordering of the input lists or vectors is not preserved.\n\n"
  917. "The optional arguments @var{secs} and @var{usecs} specify the\n"
  918. "timeout. Either @var{secs} can be specified alone, as\n"
  919. "either an integer or a real number, or both @var{secs} and\n"
  920. "@var{usecs} can be specified as integers, in which case\n"
  921. "@var{usecs} is an additional timeout expressed in\n"
  922. "microseconds. If @var{secs} is omitted or is @code{#f} then\n"
  923. "select will wait for as long as it takes for one of the other\n"
  924. "conditions to be satisfied.\n\n"
  925. "The scsh version of @code{select} differs as follows:\n"
  926. "Only vectors are accepted for the first three arguments.\n"
  927. "The @var{usecs} argument is not supported.\n"
  928. "Multiple values are returned instead of a list.\n"
  929. "Duplicates in the input vectors appear only once in output.\n"
  930. "An additional @code{select!} interface is provided.")
  931. #define FUNC_NAME s_scm_select
  932. {
  933. struct timeval timeout;
  934. struct timeval * time_ptr;
  935. SELECT_TYPE read_set;
  936. SELECT_TYPE write_set;
  937. SELECT_TYPE except_set;
  938. int read_count;
  939. int write_count;
  940. int except_count;
  941. /* these lists accumulate ports which are ready due to buffering.
  942. their file descriptors don't need to be added to the select sets. */
  943. SCM read_ports_ready = SCM_EOL;
  944. SCM write_ports_ready = SCM_EOL;
  945. int max_fd;
  946. if (SCM_VECTORP (reads))
  947. {
  948. read_count = SCM_VECTOR_LENGTH (reads);
  949. }
  950. else
  951. {
  952. read_count = scm_ilength (reads);
  953. SCM_ASSERT (read_count >= 0, reads, SCM_ARG1, FUNC_NAME);
  954. }
  955. if (SCM_VECTORP (writes))
  956. {
  957. write_count = SCM_VECTOR_LENGTH (writes);
  958. }
  959. else
  960. {
  961. write_count = scm_ilength (writes);
  962. SCM_ASSERT (write_count >= 0, writes, SCM_ARG2, FUNC_NAME);
  963. }
  964. if (SCM_VECTORP (excepts))
  965. {
  966. except_count = SCM_VECTOR_LENGTH (excepts);
  967. }
  968. else
  969. {
  970. except_count = scm_ilength (excepts);
  971. SCM_ASSERT (except_count >= 0, excepts, SCM_ARG3, FUNC_NAME);
  972. }
  973. FD_ZERO (&read_set);
  974. FD_ZERO (&write_set);
  975. FD_ZERO (&except_set);
  976. max_fd = fill_select_type (&read_set, &read_ports_ready, reads, SCM_ARG1);
  977. {
  978. int write_max = fill_select_type (&write_set, &write_ports_ready,
  979. writes, SCM_ARG2);
  980. int except_max = fill_select_type (&except_set, NULL,
  981. excepts, SCM_ARG3);
  982. if (write_max > max_fd)
  983. max_fd = write_max;
  984. if (except_max > max_fd)
  985. max_fd = except_max;
  986. }
  987. /* if there's a port with a ready buffer, don't block, just
  988. check for ready file descriptors. */
  989. if (!SCM_NULLP (read_ports_ready) || !SCM_NULLP (write_ports_ready))
  990. {
  991. timeout.tv_sec = 0;
  992. timeout.tv_usec = 0;
  993. time_ptr = &timeout;
  994. }
  995. else if (SCM_UNBNDP (secs) || SCM_FALSEP (secs))
  996. time_ptr = 0;
  997. else
  998. {
  999. if (SCM_INUMP (secs))
  1000. {
  1001. timeout.tv_sec = SCM_INUM (secs);
  1002. if (SCM_UNBNDP (usecs))
  1003. timeout.tv_usec = 0;
  1004. else
  1005. {
  1006. SCM_VALIDATE_INUM (5,usecs);
  1007. timeout.tv_usec = SCM_INUM (usecs);
  1008. }
  1009. }
  1010. else
  1011. {
  1012. double fl = scm_num2dbl (secs, FUNC_NAME);
  1013. if (!SCM_UNBNDP (usecs))
  1014. SCM_WRONG_TYPE_ARG (4, secs);
  1015. if (fl > LONG_MAX)
  1016. SCM_OUT_OF_RANGE (4, secs);
  1017. timeout.tv_sec = (long) fl;
  1018. timeout.tv_usec = (long) ((fl - timeout.tv_sec) * 1000000);
  1019. }
  1020. time_ptr = &timeout;
  1021. }
  1022. {
  1023. #ifdef GUILE_ISELECT
  1024. int rv = scm_internal_select (max_fd + 1,
  1025. &read_set, &write_set, &except_set,
  1026. time_ptr);
  1027. #else
  1028. int rv = select (max_fd + 1,
  1029. &read_set, &write_set, &except_set, time_ptr);
  1030. #endif
  1031. if (rv < 0)
  1032. SCM_SYSERROR;
  1033. }
  1034. return scm_list_3 (retrieve_select_type (&read_set, read_ports_ready, reads),
  1035. retrieve_select_type (&write_set, write_ports_ready, writes),
  1036. retrieve_select_type (&except_set, SCM_EOL, excepts));
  1037. }
  1038. #undef FUNC_NAME
  1039. #endif /* HAVE_SELECT */
  1040. #ifdef HAVE_FCNTL
  1041. SCM_DEFINE (scm_fcntl, "fcntl", 2, 1, 0,
  1042. (SCM object, SCM cmd, SCM value),
  1043. "Apply @var{command} to the specified file descriptor or the underlying\n"
  1044. "file descriptor of the specified port. @var{value} is an optional\n"
  1045. "integer argument.\n\n"
  1046. "Values for @var{command} are:\n\n"
  1047. "@table @code\n"
  1048. "@item F_DUPFD\n"
  1049. "Duplicate a file descriptor\n"
  1050. "@item F_GETFD\n"
  1051. "Get flags associated with the file descriptor.\n"
  1052. "@item F_SETFD\n"
  1053. "Set flags associated with the file descriptor to @var{value}.\n"
  1054. "@item F_GETFL\n"
  1055. "Get flags associated with the open file.\n"
  1056. "@item F_SETFL\n"
  1057. "Set flags associated with the open file to @var{value}\n"
  1058. "@item F_GETOWN\n"
  1059. "Get the process ID of a socket's owner, for @code{SIGIO} signals.\n"
  1060. "@item F_SETOWN\n"
  1061. "Set the process that owns a socket to @var{value}, for @code{SIGIO} signals.\n"
  1062. "@item FD_CLOEXEC\n"
  1063. "The value used to indicate the \"close on exec\" flag with @code{F_GETFL} or\n"
  1064. "@code{F_SETFL}.\n"
  1065. "@end table")
  1066. #define FUNC_NAME s_scm_fcntl
  1067. {
  1068. int rv;
  1069. int fdes;
  1070. int ivalue;
  1071. object = SCM_COERCE_OUTPORT (object);
  1072. SCM_VALIDATE_INUM (2,cmd);
  1073. if (SCM_OPFPORTP (object))
  1074. fdes = SCM_FPORT_FDES (object);
  1075. else
  1076. {
  1077. SCM_VALIDATE_INUM (1,object);
  1078. fdes = SCM_INUM (object);
  1079. }
  1080. if (SCM_UNBNDP (value)) {
  1081. ivalue = 0;
  1082. } else {
  1083. SCM_VALIDATE_INUM_COPY (SCM_ARG3, value, ivalue);
  1084. }
  1085. SCM_SYSCALL (rv = fcntl (fdes, SCM_INUM (cmd), ivalue));
  1086. if (rv == -1)
  1087. SCM_SYSERROR;
  1088. return SCM_MAKINUM (rv);
  1089. }
  1090. #undef FUNC_NAME
  1091. #endif /* HAVE_FCNTL */
  1092. SCM_DEFINE (scm_fsync, "fsync", 1, 0, 0,
  1093. (SCM object),
  1094. "Copies any unwritten data for the specified output file descriptor to disk.\n"
  1095. "If @var{port/fd} is a port, its buffer is flushed before the underlying\n"
  1096. "file descriptor is fsync'd.\n"
  1097. "The return value is unspecified.")
  1098. #define FUNC_NAME s_scm_fsync
  1099. {
  1100. int fdes;
  1101. object = SCM_COERCE_OUTPORT (object);
  1102. if (SCM_OPFPORTP (object))
  1103. {
  1104. scm_flush (object);
  1105. fdes = SCM_FPORT_FDES (object);
  1106. }
  1107. else
  1108. {
  1109. SCM_VALIDATE_INUM (1,object);
  1110. fdes = SCM_INUM (object);
  1111. }
  1112. if (fsync (fdes) == -1)
  1113. SCM_SYSERROR;
  1114. return SCM_UNSPECIFIED;
  1115. }
  1116. #undef FUNC_NAME
  1117. #ifdef HAVE_SYMLINK
  1118. SCM_DEFINE (scm_symlink, "symlink", 2, 0, 0,
  1119. (SCM oldpath, SCM newpath),
  1120. "Create a symbolic link named @var{path-to} with the value (i.e., pointing to)\n"
  1121. "@var{path-from}. The return value is unspecified.")
  1122. #define FUNC_NAME s_scm_symlink
  1123. {
  1124. int val;
  1125. SCM_VALIDATE_STRING (1, oldpath);
  1126. SCM_VALIDATE_STRING (2, newpath);
  1127. SCM_STRING_COERCE_0TERMINATION_X (oldpath);
  1128. SCM_STRING_COERCE_0TERMINATION_X (newpath);
  1129. SCM_SYSCALL (val = symlink (SCM_STRING_CHARS (oldpath), SCM_STRING_CHARS (newpath)));
  1130. if (val != 0)
  1131. SCM_SYSERROR;
  1132. return SCM_UNSPECIFIED;
  1133. }
  1134. #undef FUNC_NAME
  1135. #endif /* HAVE_SYMLINK */
  1136. #ifdef HAVE_READLINK
  1137. SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0,
  1138. (SCM path),
  1139. "Return the value of the symbolic link named by @var{path} (a\n"
  1140. "string), i.e., the file that the link points to.")
  1141. #define FUNC_NAME s_scm_readlink
  1142. {
  1143. int rv;
  1144. int size = 100;
  1145. char *buf;
  1146. SCM result;
  1147. SCM_VALIDATE_STRING (1, path);
  1148. SCM_STRING_COERCE_0TERMINATION_X (path);
  1149. buf = scm_must_malloc (size, FUNC_NAME);
  1150. while ((rv = readlink (SCM_STRING_CHARS (path), buf, size)) == size)
  1151. {
  1152. scm_must_free (buf);
  1153. size *= 2;
  1154. buf = scm_must_malloc (size, FUNC_NAME);
  1155. }
  1156. if (rv == -1)
  1157. {
  1158. int save_errno = errno;
  1159. free (buf);
  1160. errno = save_errno;
  1161. SCM_SYSERROR;
  1162. }
  1163. result = scm_mem2string (buf, rv);
  1164. scm_must_free (buf);
  1165. return result;
  1166. }
  1167. #undef FUNC_NAME
  1168. #endif /* HAVE_READLINK */
  1169. #ifdef HAVE_LSTAT
  1170. SCM_DEFINE (scm_lstat, "lstat", 1, 0, 0,
  1171. (SCM str),
  1172. "Similar to @code{stat}, but does not follow symbolic links, i.e.,\n"
  1173. "it will return information about a symbolic link itself, not the\n"
  1174. "file it points to. @var{path} must be a string.")
  1175. #define FUNC_NAME s_scm_lstat
  1176. {
  1177. int rv;
  1178. struct stat stat_temp;
  1179. SCM_VALIDATE_STRING (1, str);
  1180. SCM_STRING_COERCE_0TERMINATION_X (str);
  1181. SCM_SYSCALL (rv = lstat (SCM_STRING_CHARS (str), &stat_temp));
  1182. if (rv != 0)
  1183. {
  1184. int en = errno;
  1185. SCM_SYSERROR_MSG ("~A: ~S",
  1186. scm_list_2 (scm_makfrom0str (strerror (errno)), str),
  1187. en);
  1188. }
  1189. return scm_stat2scm(&stat_temp);
  1190. }
  1191. #undef FUNC_NAME
  1192. #endif /* HAVE_LSTAT */
  1193. SCM_DEFINE (scm_copy_file, "copy-file", 2, 0, 0,
  1194. (SCM oldfile, SCM newfile),
  1195. "Copy the file specified by @var{path-from} to @var{path-to}.\n"
  1196. "The return value is unspecified.")
  1197. #define FUNC_NAME s_scm_copy_file
  1198. {
  1199. int oldfd, newfd;
  1200. int n, rv;
  1201. char buf[BUFSIZ];
  1202. struct stat oldstat;
  1203. SCM_VALIDATE_STRING (1, oldfile);
  1204. SCM_STRING_COERCE_0TERMINATION_X (oldfile);
  1205. SCM_VALIDATE_STRING (2, newfile);
  1206. SCM_STRING_COERCE_0TERMINATION_X (newfile);
  1207. oldfd = open (SCM_STRING_CHARS (oldfile), O_RDONLY);
  1208. if (oldfd == -1)
  1209. SCM_SYSERROR;
  1210. SCM_SYSCALL (rv = fstat (oldfd, &oldstat));
  1211. if (rv == -1)
  1212. goto err_close_oldfd;
  1213. /* use POSIX flags instead of 07777?. */
  1214. newfd = open (SCM_STRING_CHARS (newfile), O_WRONLY | O_CREAT | O_TRUNC,
  1215. oldstat.st_mode & 07777);
  1216. if (newfd == -1)
  1217. {
  1218. err_close_oldfd:
  1219. close (oldfd);
  1220. SCM_SYSERROR;
  1221. }
  1222. while ((n = read (oldfd, buf, sizeof buf)) > 0)
  1223. if (write (newfd, buf, n) != n)
  1224. {
  1225. close (oldfd);
  1226. close (newfd);
  1227. SCM_SYSERROR;
  1228. }
  1229. close (oldfd);
  1230. if (close (newfd) == -1)
  1231. SCM_SYSERROR;
  1232. return SCM_UNSPECIFIED;
  1233. }
  1234. #undef FUNC_NAME
  1235. /* Filename manipulation */
  1236. SCM scm_dot_string;
  1237. SCM_DEFINE (scm_dirname, "dirname", 1, 0, 0,
  1238. (SCM filename),
  1239. "Return the directory name component of the file name\n"
  1240. "@var{filename}. If @var{filename} does not contain a directory\n"
  1241. "component, @code{.} is returned.")
  1242. #define FUNC_NAME s_scm_dirname
  1243. {
  1244. char *s;
  1245. long int i;
  1246. unsigned long int len;
  1247. SCM_VALIDATE_STRING (1,filename);
  1248. s = SCM_STRING_CHARS (filename);
  1249. len = SCM_STRING_LENGTH (filename);
  1250. i = len - 1;
  1251. #ifdef __MINGW32__
  1252. while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
  1253. while (i >= 0 && (s[i] != '/' && s[i] != '\\')) --i;
  1254. while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
  1255. #else
  1256. while (i >= 0 && s[i] == '/') --i;
  1257. while (i >= 0 && s[i] != '/') --i;
  1258. while (i >= 0 && s[i] == '/') --i;
  1259. #endif /* ndef __MINGW32__ */
  1260. if (i < 0)
  1261. {
  1262. #ifdef __MINGW32__
  1263. if (len > 0 && (s[0] == '/' || s[0] == '\\'))
  1264. #else
  1265. if (len > 0 && s[0] == '/')
  1266. #endif /* ndef __MINGW32__ */
  1267. return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
  1268. else
  1269. return scm_dot_string;
  1270. }
  1271. else
  1272. return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (i + 1));
  1273. }
  1274. #undef FUNC_NAME
  1275. SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
  1276. (SCM filename, SCM suffix),
  1277. "Return the base name of the file name @var{filename}. The\n"
  1278. "base name is the file name without any directory components.\n"
  1279. "If @var{suffix} is provided, and is equal to the end of\n"
  1280. "@var{basename}, it is removed also.")
  1281. #define FUNC_NAME s_scm_basename
  1282. {
  1283. char *f, *s = 0;
  1284. int i, j, len, end;
  1285. SCM_VALIDATE_STRING (1,filename);
  1286. f = SCM_STRING_CHARS (filename);
  1287. len = SCM_STRING_LENGTH (filename);
  1288. if (SCM_UNBNDP (suffix))
  1289. j = -1;
  1290. else
  1291. {
  1292. SCM_VALIDATE_STRING (2, suffix);
  1293. s = SCM_STRING_CHARS (suffix);
  1294. j = SCM_STRING_LENGTH (suffix) - 1;
  1295. }
  1296. i = len - 1;
  1297. #ifdef __MINGW32__
  1298. while (i >= 0 && (f[i] == '/' || f[i] == '\\')) --i;
  1299. #else
  1300. while (i >= 0 && f[i] == '/') --i;
  1301. #endif /* ndef __MINGW32__ */
  1302. end = i;
  1303. while (i >= 0 && j >= 0 && f[i] == s[j]) --i, --j;
  1304. if (j == -1)
  1305. end = i;
  1306. #ifdef __MINGW32__
  1307. while (i >= 0 && f[i] != '/' && f[i] != '\\') --i;
  1308. #else
  1309. while (i >= 0 && f[i] != '/') --i;
  1310. #endif /* ndef __MINGW32__ */
  1311. if (i == end)
  1312. {
  1313. #ifdef __MINGW32__
  1314. if (len > 0 && (f[0] == '/' || f[i] == '\\'))
  1315. #else
  1316. if (len > 0 && f[0] == '/')
  1317. #endif /* ndef __MINGW32__ */
  1318. return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
  1319. else
  1320. return scm_dot_string;
  1321. }
  1322. else
  1323. return scm_substring (filename, SCM_MAKINUM (i + 1), SCM_MAKINUM (end + 1));
  1324. }
  1325. #undef FUNC_NAME
  1326. void
  1327. scm_init_filesys ()
  1328. {
  1329. scm_tc16_dir = scm_make_smob_type ("directory", 0);
  1330. scm_set_smob_free (scm_tc16_dir, scm_dir_free);
  1331. scm_set_smob_print (scm_tc16_dir, scm_dir_print);
  1332. scm_dot_string = scm_permanent_object (scm_makfrom0str ("."));
  1333. #ifdef O_RDONLY
  1334. scm_c_define ("O_RDONLY", scm_long2num (O_RDONLY));
  1335. #endif
  1336. #ifdef O_WRONLY
  1337. scm_c_define ("O_WRONLY", scm_long2num (O_WRONLY));
  1338. #endif
  1339. #ifdef O_RDWR
  1340. scm_c_define ("O_RDWR", scm_long2num (O_RDWR));
  1341. #endif
  1342. #ifdef O_CREAT
  1343. scm_c_define ("O_CREAT", scm_long2num (O_CREAT));
  1344. #endif
  1345. #ifdef O_EXCL
  1346. scm_c_define ("O_EXCL", scm_long2num (O_EXCL));
  1347. #endif
  1348. #ifdef O_NOCTTY
  1349. scm_c_define ("O_NOCTTY", scm_long2num (O_NOCTTY));
  1350. #endif
  1351. #ifdef O_TRUNC
  1352. scm_c_define ("O_TRUNC", scm_long2num (O_TRUNC));
  1353. #endif
  1354. #ifdef O_APPEND
  1355. scm_c_define ("O_APPEND", scm_long2num (O_APPEND));
  1356. #endif
  1357. #ifdef O_NONBLOCK
  1358. scm_c_define ("O_NONBLOCK", scm_long2num (O_NONBLOCK));
  1359. #endif
  1360. #ifdef O_NDELAY
  1361. scm_c_define ("O_NDELAY", scm_long2num (O_NDELAY));
  1362. #endif
  1363. #ifdef O_SYNC
  1364. scm_c_define ("O_SYNC", scm_long2num (O_SYNC));
  1365. #endif
  1366. #ifdef F_DUPFD
  1367. scm_c_define ("F_DUPFD", scm_long2num (F_DUPFD));
  1368. #endif
  1369. #ifdef F_GETFD
  1370. scm_c_define ("F_GETFD", scm_long2num (F_GETFD));
  1371. #endif
  1372. #ifdef F_SETFD
  1373. scm_c_define ("F_SETFD", scm_long2num (F_SETFD));
  1374. #endif
  1375. #ifdef F_GETFL
  1376. scm_c_define ("F_GETFL", scm_long2num (F_GETFL));
  1377. #endif
  1378. #ifdef F_SETFL
  1379. scm_c_define ("F_SETFL", scm_long2num (F_SETFL));
  1380. #endif
  1381. #ifdef F_GETOWN
  1382. scm_c_define ("F_GETOWN", scm_long2num (F_GETOWN));
  1383. #endif
  1384. #ifdef F_SETOWN
  1385. scm_c_define ("F_SETOWN", scm_long2num (F_SETOWN));
  1386. #endif
  1387. #ifdef FD_CLOEXEC
  1388. scm_c_define ("FD_CLOEXEC", scm_long2num (FD_CLOEXEC));
  1389. #endif
  1390. #include "libguile/filesys.x"
  1391. }
  1392. /*
  1393. Local Variables:
  1394. c-file-style: "gnu"
  1395. End:
  1396. */