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) 157 return(-errno); 158 return(0); 159 } 160 161 int fsync_file(int fd, int datasync) 162 { 163 int ret; 164 if (datasync) 165 ret = fdatasync(fd); 166 else 167 ret = fsync(fd); 168 169 if (ret < 0) 170 return -errno; 171 return 0; 172 } 173 174 void close_file(void *stream) 175 { 176 close(*((int *) stream)); 177 } 178 179 void close_dir(void *stream) 180 { 181 closedir(stream); 182 } 183 184 int file_create(char *name, int ur, int uw, int ux, int gr, 185 int gw, int gx, int or, int ow, int ox) 186 { 187 int mode, fd; 188 189 mode = 0; 190 mode |= ur ? S_IRUSR : 0; 191 mode |= uw ? S_IWUSR : 0; 192 mode |= ux ? S_IXUSR : 0; 193 mode |= gr ? S_IRGRP : 0; 194 mode |= gw ? S_IWGRP : 0; 195 mode |= gx ? S_IXGRP : 0; 196 mode |= or ? S_IROTH : 0; 197 mode |= ow ? S_IWOTH : 0; 198 mode |= ox ? S_IXOTH : 0; 199 fd = open64(name, O_CREAT | O_RDWR, mode); 200 if(fd < 0) 201 return(-errno); 202 return(fd); 203 } 204 205 int set_attr(const char *file, struct hostfs_iattr *attrs) 206 { 207 struct utimbuf buf; 208 int err, ma; 209 210 if(attrs->ia_valid & HOSTFS_ATTR_MODE){ 211 if(chmod(file, attrs->ia_mode) != 0) return(-errno); 212 } 213 if(attrs->ia_valid & HOSTFS_ATTR_UID){ 214 if(chown(file, attrs->ia_uid, -1)) return(-errno); 215 } 216 if(attrs->ia_valid & HOSTFS_ATTR_GID){ 217 if(chown(file, -1, attrs->ia_gid)) return(-errno); 218 } 219 if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ 220 if(truncate(file, attrs->ia_size)) return(-errno); 221 } 222 ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; 223 if((attrs->ia_valid & ma) == ma){ 224 buf.actime = attrs->ia_atime.tv_sec; 225 buf.modtime = attrs->ia_mtime.tv_sec; 226 if(utime(file, &buf) != 0) return(-errno); 227 } 228 else { 229 struct timespec ts; 230 231 if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ 232 err = stat_file(file, NULL, NULL, NULL, NULL, NULL, 233 NULL, NULL, &ts, NULL, NULL, NULL); 234 if(err != 0) 235 return(err); 236 buf.actime = attrs->ia_atime.tv_sec; 237 buf.modtime = ts.tv_sec; 238 if(utime(file, &buf) != 0) 239 return(-errno); 240 } 241 if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ 242 err = stat_file(file, NULL, NULL, NULL, NULL, NULL, 243 NULL, &ts, NULL, NULL, NULL, NULL); 244 if(err != 0) 245 return(err); 246 buf.actime = ts.tv_sec; 247 buf.modtime = attrs->ia_mtime.tv_sec; 248 if(utime(file, &buf) != 0) 249 return(-errno); 250 } 251 } 252 if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; 253 if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ 254 err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, 255 &attrs->ia_atime, &attrs->ia_mtime, NULL, 256 NULL, NULL); 257 if(err != 0) return(err); 258 } 259 return(0); 260 } 261 262 int make_symlink(const char *from, const char *to) 263 { 264 int err; 265 266 err = symlink(to, from); 267 if(err) return(-errno); 268 return(0); 269 } 270 271 int unlink_file(const char *file) 272 { 273 int err; 274 275 err = unlink(file); 276 if(err) return(-errno); 277 return(0); 278 } 279 280 int do_mkdir(const char *file, int mode) 281 { 282 int err; 283 284 err = mkdir(file, mode); 285 if(err) return(-errno); 286 return(0); 287 } 288 289 int do_rmdir(const char *file) 290 { 291 int err; 292 293 err = rmdir(file); 294 if(err) return(-errno); 295 return(0); 296 } 297 298 int do_mknod(const char *file, int mode, int dev) 299 { 300 int err; 301 302 err = mknod(file, mode, dev); 303 if(err) return(-errno); 304 return(0); 305 } 306 307 int link_file(const char *to, const char *from) 308 { 309 int err; 310 311 err = link(to, from); 312 if(err) return(-errno); 313 return(0); 314 } 315 316 int do_readlink(char *file, char *buf, int size) 317 { 318 int n; 319 320 n = readlink(file, buf, size); 321 if(n < 0) 322 return(-errno); 323 if(n < size) 324 buf[n] = '\0'; 325 return(n); 326 } 327 328 int rename_file(char *from, char *to) 329 { 330 int err; 331 332 err = rename(from, to); 333 if(err < 0) return(-errno); 334 return(0); 335 } 336 337 int do_statfs(char *root, long *bsize_out, long long *blocks_out, 338 long long *bfree_out, long long *bavail_out, 339 long long *files_out, long long *ffree_out, 340 void *fsid_out, int fsid_size, long *namelen_out, 341 long *spare_out) 342 { 343 struct statfs64 buf; 344 int err; 345 346 err = statfs64(root, &buf); 347 if(err < 0) return(-errno); 348 *bsize_out = buf.f_bsize; 349 *blocks_out = buf.f_blocks; 350 *bfree_out = buf.f_bfree; 351 *bavail_out = buf.f_bavail; 352 *files_out = buf.f_files; 353 *ffree_out = buf.f_ffree; 354 memcpy(fsid_out, &buf.f_fsid, 355 sizeof(buf.f_fsid) > fsid_size ? fsid_size : 356 sizeof(buf.f_fsid)); 357 *namelen_out = buf.f_namelen; 358 spare_out[0] = buf.f_spare[0]; 359 spare_out[1] = buf.f_spare[1]; 360 spare_out[2] = buf.f_spare[2]; 361 spare_out[3] = buf.f_spare[3]; 362 spare_out[4] = buf.f_spare[4]; 363 spare_out[5] = buf.f_spare[5]; 364 return(0); 365 } 366 367 /* 368 * Overrides for Emacs so that we follow Linus's tabbing style. 369 * Emacs will notice this stuff at the end of the file and automatically 370 * adjust the settings for this buffer only. This must remain at the end 371 * of the file. 372 * --------------------------------------------------------------------------- 373 * Local variables: 374 * c-file-style: "linux" 375 * End: 376 */ 377