define STREQ, STRNEQ, STREQLEN, STRCASEQ, etc.
[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   ret->blksize = statbuf.st_blksize;
65   ret->blocks = statbuf.st_blocks;
66   ret->atime = statbuf.st_atime;
67   ret->mtime = statbuf.st_mtime;
68   ret->ctime = statbuf.st_ctime;
69
70   return ret;
71 }
72
73 guestfs_int_stat *
74 do_lstat (const char *path)
75 {
76   int r;
77   guestfs_int_stat *ret;
78   struct stat statbuf;
79
80   CHROOT_IN;
81   r = lstat (path, &statbuf);
82   CHROOT_OUT;
83
84   if (r == -1) {
85     reply_with_perror ("stat");
86     return NULL;
87   }
88
89   ret = malloc (sizeof *ret);
90   if (ret == NULL) {
91     reply_with_perror ("malloc");
92     return NULL;
93   }
94
95   ret->dev = statbuf.st_dev;
96   ret->ino = statbuf.st_ino;
97   ret->mode = statbuf.st_mode;
98   ret->nlink = statbuf.st_nlink;
99   ret->uid = statbuf.st_uid;
100   ret->gid = statbuf.st_gid;
101   ret->rdev = statbuf.st_rdev;
102   ret->size = statbuf.st_size;
103   ret->blksize = statbuf.st_blksize;
104   ret->blocks = statbuf.st_blocks;
105   ret->atime = statbuf.st_atime;
106   ret->mtime = statbuf.st_mtime;
107   ret->ctime = statbuf.st_ctime;
108
109   return ret;
110 }
111
112 guestfs_int_stat_list *
113 do_lstatlist (const char *path, char *const *names)
114 {
115   int path_fd;
116   guestfs_int_stat_list *ret;
117   size_t i, nr_names;
118
119   nr_names = count_strings (names);
120
121   ret = malloc (sizeof *ret);
122   if (!ret) {
123     reply_with_perror ("malloc");
124     return NULL;
125   }
126   ret->guestfs_int_stat_list_len = nr_names;
127   ret->guestfs_int_stat_list_val = calloc (nr_names, sizeof (guestfs_int_stat));
128   if (ret->guestfs_int_stat_list_val == NULL) {
129     reply_with_perror ("malloc");
130     free (ret);
131     return NULL;
132   }
133
134   CHROOT_IN;
135   path_fd = open (path, O_RDONLY | O_DIRECTORY);
136   CHROOT_OUT;
137
138   if (path_fd == -1) {
139     reply_with_perror ("lstatlist: %s", path);
140     free (ret->guestfs_int_stat_list_val);
141     free (ret);
142     return NULL;
143   }
144
145   for (i = 0; names[i] != NULL; ++i) {
146     int r;
147     struct stat statbuf;
148
149     r = fstatat (path_fd, names[i], &statbuf, AT_SYMLINK_NOFOLLOW);
150     if (r == -1)
151       ret->guestfs_int_stat_list_val[i].ino = -1;
152     else {
153       ret->guestfs_int_stat_list_val[i].dev = statbuf.st_dev;
154       ret->guestfs_int_stat_list_val[i].ino = statbuf.st_ino;
155       ret->guestfs_int_stat_list_val[i].mode = statbuf.st_mode;
156       ret->guestfs_int_stat_list_val[i].nlink = statbuf.st_nlink;
157       ret->guestfs_int_stat_list_val[i].uid = statbuf.st_uid;
158       ret->guestfs_int_stat_list_val[i].gid = statbuf.st_gid;
159       ret->guestfs_int_stat_list_val[i].rdev = statbuf.st_rdev;
160       ret->guestfs_int_stat_list_val[i].size = statbuf.st_size;
161       ret->guestfs_int_stat_list_val[i].blksize = statbuf.st_blksize;
162       ret->guestfs_int_stat_list_val[i].blocks = statbuf.st_blocks;
163       ret->guestfs_int_stat_list_val[i].atime = statbuf.st_atime;
164       ret->guestfs_int_stat_list_val[i].mtime = statbuf.st_mtime;
165       ret->guestfs_int_stat_list_val[i].ctime = statbuf.st_ctime;
166     }
167   }
168
169   if (close (path_fd) == -1) {
170     reply_with_perror ("close: %s", path);
171     free (ret->guestfs_int_stat_list_val);
172     free (ret);
173     return NULL;
174   }
175
176   return ret;
177 }
178
179 guestfs_int_statvfs *
180 do_statvfs (const char *path)
181 {
182   int r;
183   guestfs_int_statvfs *ret;
184   struct statvfs statbuf;
185
186   CHROOT_IN;
187   r = statvfs (path, &statbuf);
188   CHROOT_OUT;
189
190   if (r == -1) {
191     reply_with_perror ("statvfs");
192     return NULL;
193   }
194
195   ret = malloc (sizeof *ret);
196   if (ret == NULL) {
197     reply_with_perror ("malloc");
198     return NULL;
199   }
200
201   ret->bsize = statbuf.f_bsize;
202   ret->frsize = statbuf.f_frsize;
203   ret->blocks = statbuf.f_blocks;
204   ret->bfree = statbuf.f_bfree;
205   ret->bavail = statbuf.f_bavail;
206   ret->files = statbuf.f_files;
207   ret->ffree = statbuf.f_ffree;
208   ret->favail = statbuf.f_favail;
209   ret->fsid = statbuf.f_fsid;
210   ret->flag = statbuf.f_flag;
211   ret->namemax = statbuf.f_namemax;
212
213   return ret;
214 }