Version 0.6
[libguestfs.git] / daemon / file.c
1 /* libguestfs - the guestfsd daemon
2  * Copyright (C) 2009 Red Hat Inc. 
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #define _GNU_SOURCE             /* for futimens(2) */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/stat.h>
29
30 #include "../src/guestfs_protocol.h"
31 #include "daemon.h"
32 #include "actions.h"
33
34 int
35 do_touch (const char *path)
36 {
37   int fd;
38
39   NEED_ROOT (-1);
40   ABS_PATH (path, -1);
41
42   CHROOT_IN;
43   fd = open (path, O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK, 0666);
44   CHROOT_OUT;
45
46   if (fd == -1) {
47     reply_with_perror ("open: %s", path);
48     return -1;
49   }
50
51   if (futimens (fd, NULL) == -1) {
52     reply_with_perror ("futimens: %s", path);
53     close (fd);
54     return -1;
55   }
56
57   close (fd);
58   return 0;
59 }
60
61 char *
62 do_cat (const char *path)
63 {
64   int fd;
65   int alloc, size, r, max;
66   char *buf, *buf2;
67
68   NEED_ROOT (NULL);
69   ABS_PATH (path,NULL);
70
71   CHROOT_IN;
72   fd = open (path, O_RDONLY);
73   CHROOT_OUT;
74
75   if (fd == -1) {
76     reply_with_perror ("open: %s", path);
77     return NULL;
78   }
79
80   /* Read up to GUESTFS_MESSAGE_MAX - <overhead> bytes.  If it's
81    * larger than that, we need to return an error instead (for
82    * correctness).
83    */
84   max = GUESTFS_MESSAGE_MAX - 1000;
85   buf = NULL;
86   size = alloc = 0;
87
88   for (;;) {
89     if (size >= alloc) {
90       alloc += 8192;
91       if (alloc > max) {
92         reply_with_error ("cat: %s: file is too large for message buffer",
93                           path);
94         free (buf);
95         close (fd);
96         return NULL;
97       }
98       buf2 = realloc (buf, alloc);
99       if (buf2 == NULL) {
100         reply_with_perror ("realloc");
101         free (buf);
102         close (fd);
103         return NULL;
104       }
105       buf = buf2;
106     }
107
108     r = read (fd, buf + size, alloc - size);
109     if (r == -1) {
110       reply_with_perror ("read: %s", path);
111       free (buf);
112       close (fd);
113       return NULL;
114     }
115     if (r == 0) {
116       buf[size] = '\0';
117       break;
118     }
119     if (r > 0)
120       size += r;
121   }
122
123   if (close (fd) == -1) {
124     reply_with_perror ("close: %s", path);
125     free (buf);
126     return NULL;
127   }
128
129   return buf;                   /* caller will free */
130 }