/** * Create a file or directory that hides path below branch_rw */ static int do_create_whiteout(const char *path, int branch_rw, enum whiteout mode) { DBG("%s\n", path); char metapath[PATHLEN_MAX]; if (BUILD_PATH(metapath, METADIR, path)) RETURN(-1); // p MUST be without path to branch prefix here! 2 x branch_rw is correct here! // this creates e.g. branch/.unionfs/some_directory path_create_cutlast(metapath, branch_rw, branch_rw); char p[PATHLEN_MAX]; if (BUILD_PATH(p, uopt.branches[branch_rw].path, metapath)) RETURN(-1); strcat(p, HIDETAG); // TODO check length int res; if (mode == WHITEOUT_FILE) { res = open(p, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (res == -1) RETURN(-1); res = close(res); } else { res = mkdir(p, S_IRWXU); if (res) USYSLOG(LOG_ERR, "Creating %s failed: %s\n", p, strerror(errno)); } RETURN(res); }
/** * Create a file or directory that hides path below root_rw */ static int do_create_whiteout(const char *path, int root_rw, enum whiteout mode) { char metapath[PATHLEN_MAX]; int res = -1; to_root(); // whiteouts are root business if (BUILD_PATH(metapath, METADIR, path)) { syslog (LOG_WARNING, "%s(): Path too long\n", __func__); goto out; } // p MUST be without path to branch prefix here! 2 x root_rw is correct here! // this creates e.g. branch/.unionfs/some_directory path_create_cutlast(metapath, root_rw, root_rw); char p[PATHLEN_MAX]; if (BUILD_PATH(p, uopt.roots[root_rw].path, metapath, HIDETAG)) { syslog (LOG_WARNING, "%s(): Path too long\n", __func__); goto out; } if (mode == WHITEOUT_FILE) { res = open(p, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (res == -1) goto out; res = close(res); } else res = mkdir(p, S_IRWXU); out: to_user(); return res; }
/** * initiate the cow-copy action */ int cow_cp(const char *path, int branch_ro, int branch_rw, bool copy_dir) { DBG("%s\n", path); // create the path to the file path_create_cutlast(path, branch_ro, branch_rw); char from[PATHLEN_MAX], to[PATHLEN_MAX]; if (BUILD_PATH(from, uopt.branches[branch_ro].path, path)) RETURN(-ENAMETOOLONG); if (BUILD_PATH(to, uopt.branches[branch_rw].path, path)) RETURN(-ENAMETOOLONG); setlocale(LC_ALL, ""); struct cow cow; cow.uid = getuid(); // Copy the umask for explicit mode setting. cow.umask = umask(0); umask(cow.umask); cow.from_path = from; cow.to_path = to; struct stat buf; lstat(cow.from_path, &buf); cow.stat = &buf; int res; switch (buf.st_mode & S_IFMT) { case S_IFLNK: res = copy_link(&cow); break; case S_IFDIR: if (copy_dir) { res = copy_directory(path, branch_ro, branch_rw); } else { res = path_create(path, branch_ro, branch_rw); } break; case S_IFBLK: case S_IFCHR: res = copy_special(&cow); break; case S_IFIFO: res = copy_fifo(&cow); break; case S_IFSOCK: USYSLOG(LOG_WARNING, "COW of sockets not supported: %s\n", cow.from_path); RETURN(1); default: res = copy_file(&cow); } RETURN(res); }
/** * initiate the cow-copy action */ int cow_cp(const char *path, int branch_ro, int branch_rw) { DBG_IN(); // create the path to the file path_create_cutlast(path, branch_ro, branch_rw); char from[PATHLEN_MAX], to[PATHLEN_MAX]; snprintf(from, PATHLEN_MAX, "%s%s", uopt.branches[branch_ro].path, path); snprintf(to, PATHLEN_MAX, "%s%s", uopt.branches[branch_rw].path, path); setlocale(LC_ALL, ""); struct cow cow; cow.uid = getuid(); // Copy the umask for explicit mode setting. cow.umask = umask(0); umask(cow.umask); cow.from_path = from; cow.to_path = to; struct stat buf; lstat(cow.from_path, &buf); cow.stat = &buf; int res; switch (buf.st_mode & S_IFMT) { case S_IFLNK: res = copy_link(&cow); break; case S_IFDIR: res = copy_directory(path, branch_ro, branch_rw); break; case S_IFBLK: case S_IFCHR: res = copy_special(&cow); break; case S_IFIFO: res = copy_fifo(&cow); break; case S_IFSOCK: usyslog(LOG_WARNING, "COW of sockets not supported: %s\n", cow.from_path); return 1; default: res = copy_file(&cow); } return res; }