filesys.c 39 KB

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