int evdev_register_device(evdev_device_info_t *info) { dev_t minor; evdev_device_t *dev = heapmm_alloc(sizeof(evdev_device_t)); if (!dev) return ENOMEM; minor = evdev_minor_counter++; dev->info = info; dev->queue_count = 0; dev->event_wait = 0; llist_create(&(dev->queue)); evdev_list[minor] = dev; info->device = MAKEDEV(EVDEV_MAJOR, minor); return 0; }
static int stat_xattr(const char *fname, STRUCT_STAT *fst) { int mode, rdev_major, rdev_minor, uid, gid, len; char buf[256]; if (am_root >= 0 || IS_DEVICE(fst->st_mode) || IS_SPECIAL(fst->st_mode)) return -1; len = sys_lgetxattr(fname, XSTAT_ATTR, buf, sizeof buf - 1); if (len >= (int)sizeof buf) { len = -1; errno = ERANGE; } if (len < 0) { if (errno == ENOTSUP || errno == ENOATTR) return -1; if (errno == EPERM && S_ISLNK(fst->st_mode)) { fst->st_uid = 0; fst->st_gid = 0; return 0; } fprintf(stderr, "failed to read xattr %s for %s: %s\n", XSTAT_ATTR, fname, strerror(errno)); return -1; } buf[len] = '\0'; if (sscanf(buf, "%o %d,%d %d:%d", &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) { fprintf(stderr, "Corrupt %s xattr attached to %s: \"%s\"\n", XSTAT_ATTR, fname, buf); exit(1); } #if _S_IFLNK != 0120000 if ((mode & (_S_IFMT)) == 0120000) mode = (mode & ~(_S_IFMT)) | _S_IFLNK; #endif fst->st_mode = mode; fst->st_rdev = MAKEDEV(rdev_major, rdev_minor); fst->st_uid = uid; fst->st_gid = gid; return 0; }
/* **************************************************************** * Obtém entradas na tabela "disktb" * **************************************************************** */ DISKTB * disktb_attach_entries (int part_letter, int major, int unit, int target) { DISKTB *up; DISKTB *begin_up; int minor; char letter; /* * Função simples, supondo 2 entradas, uma * para o disco todo e uma para uma partição */ /* * Em primeiro lugar, procura a última entrada "sd...." */ for (up = next_disktb - 1; /* abaixo */; up--) { if (up < disktb) { letter = 'a'; break; } if (up->p_name[0] == 's' && up->p_name[1] == 'd') { letter = up->p_name[2] + 1; break; } } /* * Verifica se há espaço na "disktb" */ begin_up = up = next_disktb; minor = up - disktb; if (up + 2 >= end_disktb) { printf ( "sd%c: Tabela de Discos/Partições cheia\n", letter ); u.u_error = ENXIO; return (NODISKTB); } /* * Entrada para o disco todo */ up->p_name[0] = 's'; up->p_name[1] = 'd'; up->p_name[2] = letter; up->p_name[3] = '\0'; up->p_offset = 0; up->p_size = BL4SZ / BLSZ; /* Provisório, para ler a "parttb" */ up->p_dev = MAKEDEV (major, minor); up->p_unit = unit; up->p_target = target; /*** up->p_type = 0; ***/ /*** up->p_flags = 0; ***/ /*** up->p_head = 0; ***/ /*** up->p_sect = 0; ***/ /*** up->p_cyl = 0; ***/ up++; minor++; /* * Entrada para uma partição */ up->p_name[0] = 's'; up->p_name[1] = 'd'; up->p_name[2] = letter; up->p_name[3] = part_letter; up->p_name[4] = '\0'; up->p_offset = 0; /* Ainda desconhecido */ up->p_size = BL4SZ / BLSZ; /* Provisório, para ler a "parttb" */ up->p_dev = MAKEDEV (major, minor); up->p_unit = unit; up->p_target = target; /*** up->p_type = 0; ***/ /*** up->p_flags = 0; ***/ /*** up->p_head = 0; ***/ /*** up->p_sect = 0; ***/ /*** up->p_cyl = 0; ***/ /*** up->p_nopen = 0; ***/ /*** up->p_lock = 0; ***/ up++; up->p_name[0] = '\0'; next_disktb = up; /* * Retorna o índice da primeira entrada */ return (begin_up); } /* end disktb_attach_entries */
/* If we have a --backup-dir, then we get here from make_backup(). * We will move the file to be deleted into a parallel directory tree. */ static int keep_backup(const char *fname) { STRUCT_STAT st; struct file_struct *file; char *buf; int kept = 0; int ret_code; /* return if no file to keep */ if (do_lstat(fname, &st) < 0) return 1; if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) return 1; /* the file could have disappeared */ if (!(buf = get_backup_name(fname))) { unmake_file(file); return 0; } /* Check to see if this is a device file, or link */ if ((am_root && preserve_devices && IS_DEVICE(file->mode)) || (preserve_specials && IS_SPECIAL(file->mode))) { uint32 *devp = F_RDEV_P(file); dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); do_unlink(buf); if (do_mknod(buf, file->mode, rdev) < 0 && (errno != ENOENT || make_bak_dir(buf) < 0 || do_mknod(buf, file->mode, rdev) < 0)) { rsyserr(FERROR, errno, "mknod %s failed", full_fname(buf)); } else if (verbose > 2) { rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname); } kept = 1; do_unlink(fname); } if (!kept && S_ISDIR(file->mode)) { /* make an empty directory */ if (do_mkdir(buf, file->mode) < 0 && (errno != ENOENT || make_bak_dir(buf) < 0 || do_mkdir(buf, file->mode) < 0)) { rsyserr(FINFO, errno, "mkdir %s failed", full_fname(buf)); } ret_code = do_rmdir(fname); if (verbose > 2) { rprintf(FINFO, "make_backup: RMDIR %s returns %i\n", full_fname(fname), ret_code); } kept = 1; } #ifdef SUPPORT_LINKS if (!kept && preserve_links && S_ISLNK(file->mode)) { const char *sl = F_SYMLINK(file); if (safe_symlinks && unsafe_symlink(sl, buf)) { if (verbose) { rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n", full_fname(buf), sl); } kept = 1; } else { do_unlink(buf); if (do_symlink(sl, buf) < 0 && (errno != ENOENT || make_bak_dir(buf) < 0 || do_symlink(sl, buf) < 0)) { rsyserr(FERROR, errno, "link %s -> \"%s\"", full_fname(buf), sl); } do_unlink(fname); kept = 1; } } #endif if (!kept && !S_ISREG(file->mode)) { rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname); unmake_file(file); return 1; } /* move to keep tree if a file */ if (!kept) { if (robust_move(fname, buf) != 0) { rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"", full_fname(fname), buf); } else if (st.st_nlink > 1) { /* If someone has hard-linked the file into the backup * dir, rename() might return success but do nothing! */ robust_unlink(fname); /* Just in case... */ } } set_file_attrs(buf, file, NULL, 0); unmake_file(file); if (verbose > 1) { rprintf(FINFO, "backed up %s to %s\n", fname, buf); } return 1; }