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