1 /* 2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6 #include <unistd.h> 7 #include <stdio.h> 8 #include <fcntl.h> 9 #include <dirent.h> 10 #include <errno.h> 11 #include <utime.h> 12 #include <string.h> 13 #include <sys/stat.h> 14 #include <sys/time.h> 15 #include <sys/vfs.h> 16 #include "hostfs.h" 17 #include "kern_util.h" 18 #include "user.h" 19 20 int stat_file(const char *path, unsigned long long *inode_out, int *mode_out, 21 int *nlink_out, int *uid_out, int *gid_out, 22 unsigned long long *size_out, struct timespec *atime_out, 23 struct timespec *mtime_out, struct timespec *ctime_out, 24 int *blksize_out, unsigned long long *blocks_out) 25 { 26 struct stat64 buf; 27 28 if(lstat64(path, &buf) < 0) 29 return(-errno); 30 31 if(inode_out != NULL) *inode_out = buf.st_ino; 32 if(mode_out != NULL) *mode_out = buf.st_mode; 33 if(nlink_out != NULL) *nlink_out = buf.st_nlink; 34 if(uid_out != NULL) *uid_out = buf.st_uid; 35 if(gid_out != NULL) *gid_out = buf.st_gid; 36 if(size_out != NULL) *size_out = buf.st_size; 37 if(atime_out != NULL) { 38 atime_out->tv_sec = buf.st_atime; 39 atime_out->tv_nsec = 0; 40 } 41 if(mtime_out != NULL) { 42 mtime_out->tv_sec = buf.st_mtime; 43 mtime_out->tv_nsec = 0; 44 } 45 if(ctime_out != NULL) { 46 ctime_out->tv_sec = buf.st_ctime; 47 ctime_out->tv_nsec = 0; 48 } 49 if(blksize_out != NULL) *blksize_out = buf.st_blksize; 50 if(blocks_out != NULL) *blocks_out = buf.st_blocks; 51 return(0); 52 } 53 54 int file_type(const char *path, int *maj, int *min) 55 { 56 struct stat64 buf; 57 58 if(lstat64(path, &buf) < 0) 59 return(-errno); 60 /*We cannot pass rdev as is because glibc and the kernel disagree 61 *about its definition.*/ 62 if(maj != NULL) 63 *maj = major(buf.st_rdev); 64 if(min != NULL) 65 *min = minor(buf.st_rdev); 66 67 if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); 68 else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); 69 else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); 70 else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); 71 else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO); 72 else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK); 73 else return(OS_TYPE_FILE); 74 } 75 76 int access_file(char *path, int r, int w, int x) 77 { 78 int mode = 0; 79 80 if(r) mode = R_OK; 81 if(w) mode |= W_OK; 82 if(x) mode |= X_OK; 83 if(access(path, mode) != 0) return(-errno); 84 else return(0); 85 } 86 87 int open_file(char *path, int r, int w, int append) 88 { 89 int mode = 0, fd; 90 91 if(r && !w) 92 mode = O_RDONLY; 93 else if(!r && w) 94 mode = O_WRONLY; 95 else if(r && w) 96 mode = O_RDWR; 97 else panic("Impossible mode in open_file"); 98 99 if(append) 100 mode |= O_APPEND; 101 fd = open64(path, mode); 102 if(fd < 0) return(-errno); 103 else return(fd); 104 } 105 106 void *open_dir(char *path, int *err_out) 107 { 108 DIR *dir; 109 110 dir = opendir(path); 111 *err_out = errno; 112 if(dir == NULL) return(NULL); 113 return(dir); 114 } 115 116 char *read_dir(void *stream, unsigned long long *pos, 117 unsigned long long *ino_out, int *len_out) 118 { 119 DIR *dir = stream; 120 struct dirent *ent; 121 122 seekdir(dir, *pos); 123 ent = readdir(dir); 124 if(ent == NULL) return(NULL); 125 *len_out = strlen(ent->d_name); 126 *ino_out = ent->d_ino; 127 *pos = telldir(dir); 128 return(ent->d_name); 129 } 130 131 int read_file(int fd, unsigned long long *offset, char *buf, int len) 132 { 133 int n; 134 135 n = pread64(fd, buf, len, *offset); 136 if(n < 0) return(-errno); 137 *offset += n; 138 return(n); 139 } 140 141 int write_file(int fd, unsigned long long *offset, const char *buf, int len) 142 { 143 int n; 144 145 n = pwrite64(fd, buf, len, *offset); 146 if(n < 0) return(-errno); 147 *offset += n; 148 return(n); 149 } 150 151 int lseek_file(int fd, long long offset, int whence) 152 { 153 int ret; 154 155 ret = lseek64(fd, offset, whence); 156 if(ret < 0) return(-errno); 157 return(0); 158 } 159 160 void close_file(void *stream) 161 { 162 close(*((int *) stream)); 163 } 164 165 void close_dir(void *stream) 166 { 167 closedir(stream); 168 } 169 170 int file_create(char *name, int ur, int uw, int ux, int gr, 171 int gw, int gx, int or, int ow, int ox) 172 { 173 int mode, fd; 174 175 mode = 0; 176 mode |= ur ? S_IRUSR : 0; 177 mode |= uw ? S_IWUSR : 0; 178 mode |= ux ? S_IXUSR : 0; 179 mode |= gr ? S_IRGRP : 0; 180 mode |= gw ? S_IWGRP : 0; 181 mode |= gx ? S_IXGRP : 0; 182 mode |= or ? S_IROTH : 0; 183 mode |= ow ? S_IWOTH : 0; 184 mode |= ox ? S_IXOTH : 0; 185 fd = open64(name, O_CREAT | O_RDWR, mode); 186 if(fd < 0) 187 return(-errno); 188 return(fd); 189 } 190 191 int set_attr(const char *file, struct hostfs_iattr *attrs) 192 { 193 struct utimbuf buf; 194 int err, ma; 195 196 if(attrs->ia_valid & HOSTFS_ATTR_MODE){ 197 if(chmod(file, attrs->ia_mode) != 0) return(-errno); 198 } 199 if(attrs->ia_valid & HOSTFS_ATTR_UID){ 200 if(chown(file, attrs->ia_uid, -1)) return(-errno); 201 } 202 if(attrs->ia_valid & HOSTFS_ATTR_GID){ 203 if(chown(file, -1, attrs->ia_gid)) return(-errno); 204 } 205 if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ 206 if(truncate(file, attrs->ia_size)) return(-errno); 207 } 208 ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; 209 if((attrs->ia_valid & ma) == ma){ 210 buf.actime = attrs->ia_atime.tv_sec; 211 buf.modtime = attrs->ia_mtime.tv_sec; 212 if(utime(file, &buf) != 0) return(-errno); 213 } 214 else { 215 struct timespec ts; 216 217 if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ 218 err = stat_file(file, NULL, NULL, NULL, NULL, NULL, 219 NULL, NULL, &ts, NULL, NULL, NULL); 220 if(err != 0) 221 return(err); 222 buf.actime = attrs->ia_atime.tv_sec; 223 buf.modtime = ts.tv_sec; 224 if(utime(file, &buf) != 0) 225 return(-errno); 226 } 227 if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ 228 err = stat_file(file, NULL, NULL, NULL, NULL, NULL, 229 NULL, &ts, NULL, NULL, NULL, NULL); 230 if(err != 0) 231 return(err); 232 buf.actime = ts.tv_sec; 233 buf.modtime = attrs->ia_mtime.tv_sec; 234 if(utime(file, &buf) != 0) 235 return(-errno); 236 } 237 } 238 if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; 239 if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ 240 err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, 241 &attrs->ia_atime, &attrs->ia_mtime, NULL, 242 NULL, NULL); 243 if(err != 0) return(err); 244 } 245 return(0); 246 } 247 248 int make_symlink(const char *from, const char *to) 249 { 250 int err; 251 252 err = symlink(to, from); 253 if(err) return(-errno); 254 return(0); 255 } 256 257 int unlink_file(const char *file) 258 { 259 int err; 260 261 err = unlink(file); 262 if(err) return(-errno); 263 return(0); 264 } 265 266 int do_mkdir(const char *file, int mode) 267 { 268 int err; 269 270 err = mkdir(file, mode); 271 if(err) return(-errno); 272 return(0); 273 } 274 275 int do_rmdir(const char *file) 276 { 277 int err; 278 279 err = rmdir(file); 280 if(err) return(-errno); 281 return(0); 282 } 283 284 int do_mknod(const char *file, int mode, int dev) 285 { 286 int err; 287 288 err = mknod(file, mode, dev); 289 if(err) return(-errno); 290 return(0); 291 } 292 293 int link_file(const char *to, const char *from) 294 { 295 int err; 296 297 err = link(to, from); 298 if(err) return(-errno); 299 return(0); 300 } 301 302 int do_readlink(char *file, char *buf, int size) 303 { 304 int n; 305 306 n = readlink(file, buf, size); 307 if(n < 0) 308 return(-errno); 309 if(n < size) 310 buf[n] = '\0'; 311 return(n); 312 } 313 314 int rename_file(char *from, char *to) 315 { 316 int err; 317 318 err = rename(from, to); 319 if(err < 0) return(-errno); 320 return(0); 321 } 322 323 int do_statfs(char *root, long *bsize_out, long long *blocks_out, 324 long long *bfree_out, long long *bavail_out, 325 long long *files_out, long long *ffree_out, 326 void *fsid_out, int fsid_size, long *namelen_out, 327 long *spare_out) 328 { 329 struct statfs64 buf; 330 int err; 331 332 err = statfs64(root, &buf); 333 if(err < 0) return(-errno); 334 *bsize_out = buf.f_bsize; 335 *blocks_out = buf.f_blocks; 336 *bfree_out = buf.f_bfree; 337 *bavail_out = buf.f_bavail; 338 *files_out = buf.f_files; 339 *ffree_out = buf.f_ffree; 340 memcpy(fsid_out, &buf.f_fsid, 341 sizeof(buf.f_fsid) > fsid_size ? fsid_size : 342 sizeof(buf.f_fsid)); 343 *namelen_out = buf.f_namelen; 344 spare_out[0] = buf.f_spare[0]; 345 spare_out[1] = buf.f_spare[1]; 346 spare_out[2] = buf.f_spare[2]; 347 spare_out[3] = buf.f_spare[3]; 348 spare_out[4] = buf.f_spare[4]; 349 spare_out[5] = buf.f_spare[5]; 350 return(0); 351 } 352 353 /* 354 * Overrides for Emacs so that we follow Linus's tabbing style. 355 * Emacs will notice this stuff at the end of the file and automatically 356 * adjust the settings for this buffer only. This must remain at the end 357 * of the file. 358 * --------------------------------------------------------------------------- 359 * Local variables: 360 * c-file-style: "linux" 361 * End: 362 */ 363