maint: remove unnecessary include of openat.h
[libguestfs.git] / daemon / stat.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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/statvfs.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29
30 #include "../src/guestfs_protocol.h"
31 #include "daemon.h"
32 #include "actions.h"
33
34 guestfs_int_stat *
35 do_stat (const char *path)
36 {
37   int r;
38   guestfs_int_stat *ret;
39   struct stat statbuf;
40
41   CHROOT_IN;
42   r = stat (path, &statbuf);
43   CHROOT_OUT;
44
45   if (r == -1) {
46     reply_with_perror ("stat");
47     return NULL;
48   }
49
50   ret = malloc (sizeof *ret);
51   if (ret == NULL) {
52     reply_with_perror ("malloc");
53     return NULL;
54   }
55
56   ret->dev = statbuf.st_dev;
57   ret->ino = statbuf.st_ino;
58   ret->mode = statbuf.st_mode;
59   ret->nlink = statbuf.st_nlink;
60   ret->uid = statbuf.st_uid;
61   ret->gid = statbuf.st_gid;
62   ret->rdev = statbuf.st_rdev;
63   ret->size = statbuf.st_size;
64 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
65   ret->blksize = statbuf.st_blksize;
66 #else
67   ret->blksize = -1;
68 #endif
69 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
70   ret->blocks = statbuf.st_blocks;
71 #else
72   ret->blocks = -1;
73 #endif
74   ret->atime = statbuf.st_atime;
75   ret->mtime = statbuf.st_mtime;
76   ret->ctime = statbuf.st_ctime;
77
78   return ret;
79 }
80
81 guestfs_int_stat *
82 do_lstat (const char *path)
83 {
84   int r;
85   guestfs_int_stat *ret;
86   struct stat statbuf;
87
88   CHROOT_IN;
89   r = lstat (path, &statbuf);
90   CHROOT_OUT;
91
92   if (r == -1) {
93     reply_with_perror ("stat");
94     return NULL;
95   }
96
97   ret = malloc (sizeof *ret);
98   if (ret == NULL) {
99     reply_with_perror ("malloc");
100     return NULL;
101   }
102
103   ret->dev = statbuf.st_dev;
104   ret->ino = statbuf.st_ino;
105   ret->mode = statbuf.st_mode;
106   ret->nlink = statbuf.st_nlink;
107   ret->uid = statbuf.st_uid;
108   ret->gid = statbuf.st_gid;
109   ret->rdev = statbuf.st_rdev;
110   ret->size = statbuf.st_size;
111 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
112   ret->blksize = statbuf.st_blksize;
113 #else
114   ret->blksize = -1;
115 #endif
116 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
117   ret->blocks = statbuf.st_blocks;
118 #else
119   ret->blocks = -1;
120 #endif
121   ret->atime = statbuf.st_atime;
122   ret->mtime = statbuf.st_mtime;
123   ret->ctime = statbuf.st_ctime;
124
125   return ret;
126 }
127
128 guestfs_int_stat_list *
129 do_lstatlist (const char *path, char *const *names)
130 {
131   int path_fd;
132   guestfs_int_stat_list *ret;
133   size_t i, nr_names;
134
135   nr_names = count_strings (names);
136
137   ret = malloc (sizeof *ret);
138   if (!ret) {
139     reply_with_perror ("malloc");
140     return NULL;
141   }
142   ret->guestfs_int_stat_list_len = nr_names;
143   ret->guestfs_int_stat_list_val = calloc (nr_names, sizeof (guestfs_int_stat));
144   if (ret->guestfs_int_stat_list_val == NULL) {
145     reply_with_perror ("malloc");
146     free (ret);
147     return NULL;
148   }
149
150   CHROOT_IN;
151   path_fd = open (path, O_RDONLY | O_DIRECTORY);
152   CHROOT_OUT;
153
154   if (path_fd == -1) {
155     reply_with_perror ("lstatlist: %s", path);
156     free (ret->guestfs_int_stat_list_val);
157     free (ret);
158     return NULL;
159   }
160
161   for (i = 0; names[i] != NULL; ++i) {
162     int r;
163     struct stat statbuf;
164
165     r = fstatat (path_fd, names[i], &statbuf, AT_SYMLINK_NOFOLLOW);
166     if (r == -1)
167       ret->guestfs_int_stat_list_val[i].ino = -1;
168     else {
169       ret->guestfs_int_stat_list_val[i].dev = statbuf.st_dev;
170       ret->guestfs_int_stat_list_val[i].ino = statbuf.st_ino;
171       ret->guestfs_int_stat_list_val[i].mode = statbuf.st_mode;
172       ret->guestfs_int_stat_list_val[i].nlink = statbuf.st_nlink;
173       ret->guestfs_int_stat_list_val[i].uid = statbuf.st_uid;
174       ret->guestfs_int_stat_list_val[i].gid = statbuf.st_gid;
175       ret->guestfs_int_stat_list_val[i].rdev = statbuf.st_rdev;
176       ret->guestfs_int_stat_list_val[i].size = statbuf.st_size;
177 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
178       ret->guestfs_int_stat_list_val[i].blksize = statbuf.st_blksize;
179 #else
180       ret->guestfs_int_stat_list_val[i].blksize = -1;
181 #endif
182 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
183       ret->guestfs_int_stat_list_val[i].blocks = statbuf.st_blocks;
184 #else
185       ret->guestfs_int_stat_list_val[i].blocks = -1;
186 #endif
187       ret->guestfs_int_stat_list_val[i].atime = statbuf.st_atime;
188       ret->guestfs_int_stat_list_val[i].mtime = statbuf.st_mtime;
189       ret->guestfs_int_stat_list_val[i].ctime = statbuf.st_ctime;
190     }
191   }
192
193   if (close (path_fd) == -1) {
194     reply_with_perror ("close: %s", path);
195     free (ret->guestfs_int_stat_list_val);
196     free (ret);
197     return NULL;
198   }
199
200   return ret;
201 }
202
203 guestfs_int_statvfs *
204 do_statvfs (const char *path)
205 {
206   int r;
207   guestfs_int_statvfs *ret;
208   struct statvfs statbuf;
209
210   CHROOT_IN;
211   r = statvfs (path, &statbuf);
212   CHROOT_OUT;
213
214   if (r == -1) {
215     reply_with_perror ("statvfs");
216     return NULL;
217   }
218
219   ret = malloc (sizeof *ret);
220   if (ret == NULL) {
221     reply_with_perror ("malloc");
222     return NULL;
223   }
224
225   ret->bsize = statbuf.f_bsize;
226   ret->frsize = statbuf.f_frsize;
227   ret->blocks = statbuf.f_blocks;
228   ret->bfree = statbuf.f_bfree;
229   ret->bavail = statbuf.f_bavail;
230   ret->files = statbuf.f_files;
231   ret->ffree = statbuf.f_ffree;
232   ret->favail = statbuf.f_favail;
233   ret->fsid = statbuf.f_fsid;
234   ret->flag = statbuf.f_flag;
235   ret->namemax = statbuf.f_namemax;
236
237   return ret;
238 }