file.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /*
  2. * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <signal.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <sys/socket.h>
  13. #include <sys/un.h>
  14. #include <sys/ioctl.h>
  15. #include <sys/mount.h>
  16. #include <sys/uio.h>
  17. #include "os.h"
  18. #include "user.h"
  19. #include "kern_util.h"
  20. static void copy_stat(struct uml_stat *dst, struct stat64 *src)
  21. {
  22. *dst = ((struct uml_stat) {
  23. .ust_dev = src->st_dev, /* device */
  24. .ust_ino = src->st_ino, /* inode */
  25. .ust_mode = src->st_mode, /* protection */
  26. .ust_nlink = src->st_nlink, /* number of hard links */
  27. .ust_uid = src->st_uid, /* user ID of owner */
  28. .ust_gid = src->st_gid, /* group ID of owner */
  29. .ust_size = src->st_size, /* total size, in bytes */
  30. .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
  31. .ust_blocks = src->st_blocks, /* number of blocks allocated */
  32. .ust_atime = src->st_atime, /* time of last access */
  33. .ust_mtime = src->st_mtime, /* time of last modification */
  34. .ust_ctime = src->st_ctime, /* time of last change */
  35. });
  36. }
  37. int os_stat_fd(const int fd, struct uml_stat *ubuf)
  38. {
  39. struct stat64 sbuf;
  40. int err;
  41. CATCH_EINTR(err = fstat64(fd, &sbuf));
  42. if(err < 0)
  43. return -errno;
  44. if(ubuf != NULL)
  45. copy_stat(ubuf, &sbuf);
  46. return err;
  47. }
  48. int os_stat_file(const char *file_name, struct uml_stat *ubuf)
  49. {
  50. struct stat64 sbuf;
  51. int err;
  52. do {
  53. err = stat64(file_name, &sbuf);
  54. } while((err < 0) && (errno == EINTR)) ;
  55. if(err < 0)
  56. return -errno;
  57. if(ubuf != NULL)
  58. copy_stat(ubuf, &sbuf);
  59. return err;
  60. }
  61. int os_access(const char* file, int mode)
  62. {
  63. int amode, err;
  64. amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
  65. (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
  66. err = access(file, amode);
  67. if(err < 0)
  68. return -errno;
  69. return 0;
  70. }
  71. /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
  72. int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
  73. {
  74. int err;
  75. err = ioctl(fd, cmd, arg);
  76. if(err < 0)
  77. return -errno;
  78. return err;
  79. }
  80. /* FIXME: ensure namebuf in os_get_if_name is big enough */
  81. int os_get_ifname(int fd, char* namebuf)
  82. {
  83. if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
  84. return -errno;
  85. return 0;
  86. }
  87. int os_set_slip(int fd)
  88. {
  89. int disc, sencap;
  90. disc = N_SLIP;
  91. if(ioctl(fd, TIOCSETD, &disc) < 0)
  92. return -errno;
  93. sencap = 0;
  94. if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
  95. return -errno;
  96. return 0;
  97. }
  98. int os_set_owner(int fd, int pid)
  99. {
  100. if(fcntl(fd, F_SETOWN, pid) < 0){
  101. int save_errno = errno;
  102. if(fcntl(fd, F_GETOWN, 0) != pid)
  103. return -save_errno;
  104. }
  105. return 0;
  106. }
  107. int os_mode_fd(int fd, int mode)
  108. {
  109. int err;
  110. do {
  111. err = fchmod(fd, mode);
  112. } while((err < 0) && (errno==EINTR)) ;
  113. if(err < 0)
  114. return -errno;
  115. return 0;
  116. }
  117. int os_file_type(char *file)
  118. {
  119. struct uml_stat buf;
  120. int err;
  121. err = os_stat_file(file, &buf);
  122. if(err < 0)
  123. return err;
  124. if(S_ISDIR(buf.ust_mode))
  125. return OS_TYPE_DIR;
  126. else if(S_ISLNK(buf.ust_mode))
  127. return OS_TYPE_SYMLINK;
  128. else if(S_ISCHR(buf.ust_mode))
  129. return OS_TYPE_CHARDEV;
  130. else if(S_ISBLK(buf.ust_mode))
  131. return OS_TYPE_BLOCKDEV;
  132. else if(S_ISFIFO(buf.ust_mode))
  133. return OS_TYPE_FIFO;
  134. else if(S_ISSOCK(buf.ust_mode))
  135. return OS_TYPE_SOCK;
  136. else return OS_TYPE_FILE;
  137. }
  138. int os_file_mode(char *file, struct openflags *mode_out)
  139. {
  140. int err;
  141. *mode_out = OPENFLAGS();
  142. err = access(file, W_OK);
  143. if(err && (errno != EACCES))
  144. return -errno;
  145. else if(!err)
  146. *mode_out = of_write(*mode_out);
  147. err = access(file, R_OK);
  148. if(err && (errno != EACCES))
  149. return -errno;
  150. else if(!err)
  151. *mode_out = of_read(*mode_out);
  152. return err;
  153. }
  154. int os_open_file(char *file, struct openflags flags, int mode)
  155. {
  156. int fd, err, f = 0;
  157. if(flags.r && flags.w) f = O_RDWR;
  158. else if(flags.r) f = O_RDONLY;
  159. else if(flags.w) f = O_WRONLY;
  160. else f = 0;
  161. if(flags.s) f |= O_SYNC;
  162. if(flags.c) f |= O_CREAT;
  163. if(flags.t) f |= O_TRUNC;
  164. if(flags.e) f |= O_EXCL;
  165. fd = open64(file, f, mode);
  166. if(fd < 0)
  167. return -errno;
  168. if(flags.cl && fcntl(fd, F_SETFD, 1)){
  169. err = -errno;
  170. close(fd);
  171. return err;
  172. }
  173. return fd;
  174. }
  175. int os_connect_socket(char *name)
  176. {
  177. struct sockaddr_un sock;
  178. int fd, err;
  179. sock.sun_family = AF_UNIX;
  180. snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
  181. fd = socket(AF_UNIX, SOCK_STREAM, 0);
  182. if(fd < 0) {
  183. err = -errno;
  184. goto out;
  185. }
  186. err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
  187. if(err) {
  188. err = -errno;
  189. goto out_close;
  190. }
  191. return fd;
  192. out_close:
  193. close(fd);
  194. out:
  195. return err;
  196. }
  197. void os_close_file(int fd)
  198. {
  199. close(fd);
  200. }
  201. int os_seek_file(int fd, unsigned long long offset)
  202. {
  203. unsigned long long actual;
  204. actual = lseek64(fd, offset, SEEK_SET);
  205. if(actual != offset)
  206. return -errno;
  207. return 0;
  208. }
  209. int os_read_file(int fd, void *buf, int len)
  210. {
  211. int n = read(fd, buf, len);
  212. if(n < 0)
  213. return -errno;
  214. return n;
  215. }
  216. int os_write_file(int fd, const void *buf, int len)
  217. {
  218. int n = write(fd, (void *) buf, len);
  219. if(n < 0)
  220. return -errno;
  221. return n;
  222. }
  223. int os_file_size(char *file, unsigned long long *size_out)
  224. {
  225. struct uml_stat buf;
  226. int err;
  227. err = os_stat_file(file, &buf);
  228. if(err < 0){
  229. printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
  230. return err;
  231. }
  232. if(S_ISBLK(buf.ust_mode)){
  233. int fd;
  234. long blocks;
  235. fd = open(file, O_RDONLY, 0);
  236. if(fd < 0) {
  237. err = -errno;
  238. printk("Couldn't open \"%s\", errno = %d\n", file,
  239. errno);
  240. return err;
  241. }
  242. if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
  243. err = -errno;
  244. printk("Couldn't get the block size of \"%s\", "
  245. "errno = %d\n", file, errno);
  246. close(fd);
  247. return err;
  248. }
  249. *size_out = ((long long) blocks) * 512;
  250. close(fd);
  251. }
  252. else *size_out = buf.ust_size;
  253. return 0;
  254. }
  255. int os_file_modtime(char *file, unsigned long *modtime)
  256. {
  257. struct uml_stat buf;
  258. int err;
  259. err = os_stat_file(file, &buf);
  260. if(err < 0){
  261. printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
  262. return err;
  263. }
  264. *modtime = buf.ust_mtime;
  265. return 0;
  266. }
  267. int os_get_exec_close(int fd, int *close_on_exec)
  268. {
  269. int ret;
  270. CATCH_EINTR(ret = fcntl(fd, F_GETFD));
  271. if(ret < 0)
  272. return -errno;
  273. *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
  274. return ret;
  275. }
  276. int os_set_exec_close(int fd)
  277. {
  278. int err;
  279. CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
  280. if(err < 0)
  281. return -errno;
  282. return err;
  283. }
  284. int os_pipe(int *fds, int stream, int close_on_exec)
  285. {
  286. int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
  287. err = socketpair(AF_UNIX, type, 0, fds);
  288. if(err < 0)
  289. return -errno;
  290. if(!close_on_exec)
  291. return 0;
  292. err = os_set_exec_close(fds[0]);
  293. if(err < 0)
  294. goto error;
  295. err = os_set_exec_close(fds[1]);
  296. if(err < 0)
  297. goto error;
  298. return 0;
  299. error:
  300. printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
  301. close(fds[1]);
  302. close(fds[0]);
  303. return err;
  304. }
  305. int os_set_fd_async(int fd, int owner)
  306. {
  307. int err;
  308. /* XXX This should do F_GETFL first */
  309. if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
  310. err = -errno;
  311. printk("os_set_fd_async : failed to set O_ASYNC and "
  312. "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
  313. return err;
  314. }
  315. #ifdef notdef
  316. if(fcntl(fd, F_SETFD, 1) < 0){
  317. printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
  318. "errno = %d\n", errno);
  319. }
  320. #endif
  321. if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
  322. (fcntl(fd, F_SETOWN, owner) < 0)){
  323. err = -errno;
  324. printk("os_set_fd_async : Failed to fcntl F_SETOWN "
  325. "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
  326. owner, errno);
  327. return err;
  328. }
  329. return 0;
  330. }
  331. int os_clear_fd_async(int fd)
  332. {
  333. int flags = fcntl(fd, F_GETFL);
  334. flags &= ~(O_ASYNC | O_NONBLOCK);
  335. if(fcntl(fd, F_SETFL, flags) < 0)
  336. return -errno;
  337. return 0;
  338. }
  339. int os_set_fd_block(int fd, int blocking)
  340. {
  341. int flags;
  342. flags = fcntl(fd, F_GETFL);
  343. if(blocking) flags &= ~O_NONBLOCK;
  344. else flags |= O_NONBLOCK;
  345. if(fcntl(fd, F_SETFL, flags) < 0)
  346. return -errno;
  347. return 0;
  348. }
  349. int os_accept_connection(int fd)
  350. {
  351. int new;
  352. new = accept(fd, NULL, 0);
  353. if(new < 0)
  354. return -errno;
  355. return new;
  356. }
  357. #ifndef SHUT_RD
  358. #define SHUT_RD 0
  359. #endif
  360. #ifndef SHUT_WR
  361. #define SHUT_WR 1
  362. #endif
  363. #ifndef SHUT_RDWR
  364. #define SHUT_RDWR 2
  365. #endif
  366. int os_shutdown_socket(int fd, int r, int w)
  367. {
  368. int what, err;
  369. if(r && w) what = SHUT_RDWR;
  370. else if(r) what = SHUT_RD;
  371. else if(w) what = SHUT_WR;
  372. else {
  373. printk("os_shutdown_socket : neither r or w was set\n");
  374. return -EINVAL;
  375. }
  376. err = shutdown(fd, what);
  377. if(err < 0)
  378. return -errno;
  379. return 0;
  380. }
  381. int os_rcv_fd(int fd, int *helper_pid_out)
  382. {
  383. int new, n;
  384. char buf[CMSG_SPACE(sizeof(new))];
  385. struct msghdr msg;
  386. struct cmsghdr *cmsg;
  387. struct iovec iov;
  388. msg.msg_name = NULL;
  389. msg.msg_namelen = 0;
  390. iov = ((struct iovec) { .iov_base = helper_pid_out,
  391. .iov_len = sizeof(*helper_pid_out) });
  392. msg.msg_iov = &iov;
  393. msg.msg_iovlen = 1;
  394. msg.msg_control = buf;
  395. msg.msg_controllen = sizeof(buf);
  396. msg.msg_flags = 0;
  397. n = recvmsg(fd, &msg, 0);
  398. if(n < 0)
  399. return -errno;
  400. else if(n != sizeof(iov.iov_len))
  401. *helper_pid_out = -1;
  402. cmsg = CMSG_FIRSTHDR(&msg);
  403. if(cmsg == NULL){
  404. printk("rcv_fd didn't receive anything, error = %d\n", errno);
  405. return -1;
  406. }
  407. if((cmsg->cmsg_level != SOL_SOCKET) ||
  408. (cmsg->cmsg_type != SCM_RIGHTS)){
  409. printk("rcv_fd didn't receive a descriptor\n");
  410. return -1;
  411. }
  412. new = ((int *) CMSG_DATA(cmsg))[0];
  413. return new;
  414. }
  415. int os_create_unix_socket(char *file, int len, int close_on_exec)
  416. {
  417. struct sockaddr_un addr;
  418. int sock, err;
  419. sock = socket(PF_UNIX, SOCK_DGRAM, 0);
  420. if(sock < 0)
  421. return -errno;
  422. if(close_on_exec) {
  423. err = os_set_exec_close(sock);
  424. if(err < 0)
  425. printk("create_unix_socket : close_on_exec failed, "
  426. "err = %d", -err);
  427. }
  428. addr.sun_family = AF_UNIX;
  429. /* XXX Be more careful about overflow */
  430. snprintf(addr.sun_path, len, "%s", file);
  431. err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
  432. if(err < 0)
  433. return -errno;
  434. return sock;
  435. }
  436. void os_flush_stdout(void)
  437. {
  438. fflush(stdout);
  439. }
  440. int os_lock_file(int fd, int excl)
  441. {
  442. int type = excl ? F_WRLCK : F_RDLCK;
  443. struct flock lock = ((struct flock) { .l_type = type,
  444. .l_whence = SEEK_SET,
  445. .l_start = 0,
  446. .l_len = 0 } );
  447. int err, save;
  448. err = fcntl(fd, F_SETLK, &lock);
  449. if(!err)
  450. goto out;
  451. save = -errno;
  452. err = fcntl(fd, F_GETLK, &lock);
  453. if(err){
  454. err = -errno;
  455. goto out;
  456. }
  457. printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
  458. err = save;
  459. out:
  460. return err;
  461. }