static int merge_dirs (const char *root, char **dirs, int n_dirs) { DIR *dir; char *subdirs[n_dirs]; struct dirent *dirent; struct stat st; char *src_path; char *dest_path; int conflict; int i, j; for (i = 0; i < n_dirs; i++) { if (dirs[i] == NULL) continue; dir = opendir (dirs[i]); if (dir == NULL) continue; while ((dirent = readdir (dir)) != NULL) { src_path = strconcat (dirs[i], "/", dirent->d_name); if (strcmp (dirent->d_name, ".") == 0 || strcmp (dirent->d_name, "..") == 0) continue; dest_path = strconcat (root, "/", dirent->d_name); if (lstat (dest_path, &st) == 0) { free (dest_path); continue; /* We already copyed this file */ } if (lstat (src_path, &st) < 0) { free (dest_path); continue; } if (S_ISCHR (st.st_mode) || S_ISBLK (st.st_mode) || S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode)) { fprintf (stderr, "WARNING: ignoring special file %s\n", src_path); free (dest_path); continue; } conflict = has_conflict (dirs, n_dirs, dirent->d_name, i); if (conflict == NO_CONFLICTS) { bind_file (src_path, dest_path, &st); } else if (conflict == DIR_CONFLICT) { if (mkdir (dest_path, st.st_mode & 0777)) fatal_errno ("create merged dir"); if (lchown(dest_path, st.st_uid, st.st_gid) < 0) fatal_errno ("lchown"); for (j = 0; j < n_dirs; j++) subdirs[j] = get_subdir (dirs[j], dirent->d_name); merge_dirs (dest_path, subdirs, n_dirs); for (j = 0; j < n_dirs; j++) { if (subdirs[j]) free (subdirs[j]); } } else fatal ("Filename conflicts, refusing to mount\n"); free (dest_path); } } return 0; }
/***************************************************************************** * Open: open the file *****************************************************************************/ static int Open( vlc_object_t *p_this ) { sout_access_out_t *p_access = (sout_access_out_t*)p_this; int fd; config_ChainParse( p_access, SOUT_CFG_PREFIX, ppsz_sout_options, p_access->p_cfg ); if( !p_access->psz_path ) { msg_Err( p_access, "no file name specified" ); return VLC_EGENERIC; } bool overwrite = var_GetBool (p_access, SOUT_CFG_PREFIX"overwrite"); bool append = var_GetBool( p_access, SOUT_CFG_PREFIX "append" ); if (!strcmp (p_access->psz_access, "fd")) { char *end; fd = strtol (p_access->psz_path, &end, 0); if (!*p_access->psz_path || *end) { msg_Err (p_access, "invalid file descriptor: %s", p_access->psz_path); return VLC_EGENERIC; } fd = vlc_dup (fd); if (fd == -1) { msg_Err (p_access, "cannot use file descriptor: %s", vlc_strerror_c(errno)); return VLC_EGENERIC; } } else if( !strcmp( p_access->psz_path, "-" ) ) { #if defined( _WIN32 ) || defined( __OS2__ ) setmode (STDOUT_FILENO, O_BINARY); #endif fd = vlc_dup (STDOUT_FILENO); if (fd == -1) { msg_Err (p_access, "cannot use standard output: %s", vlc_strerror_c(errno)); return VLC_EGENERIC; } msg_Dbg( p_access, "using stdout" ); } else { const char *path = p_access->psz_path; char *buf = NULL; if (var_InheritBool (p_access, SOUT_CFG_PREFIX"format")) { buf = str_format_time (path); path_sanitize (buf); path = buf; } int flags = O_RDWR | O_CREAT | O_LARGEFILE; if (!overwrite) flags |= O_EXCL; if (!append) flags |= O_TRUNC; #ifdef O_SYNC if (var_GetBool (p_access, SOUT_CFG_PREFIX"sync")) flags |= O_SYNC; #endif do { fd = vlc_open (path, flags, 0666); if (fd != -1) break; if (fd == -1) msg_Err (p_access, "cannot create %s: %s", path, vlc_strerror_c(errno)); if (overwrite || errno != EEXIST) break; flags &= ~O_EXCL; } while (dialog_Question (p_access, path, _("The output file already exists. " "If recording continues, the file will be " "overridden and its content will be lost."), _("Keep existing file"), _("Overwrite"), NULL) == 2); free (buf); if (fd == -1) return VLC_EGENERIC; } struct stat st; if (fstat (fd, &st)) { msg_Err (p_access, "write error: %s", vlc_strerror_c(errno)); close (fd); return VLC_EGENERIC; } p_access->pf_read = Read; if (S_ISREG(st.st_mode) || S_ISBLK(st.st_mode)) { p_access->pf_write = Write; p_access->pf_seek = Seek; } #ifdef S_ISSOCK else if (S_ISSOCK(st.st_mode)) { p_access->pf_write = Send; p_access->pf_seek = NoSeek; } #endif else { p_access->pf_write = WritePipe; p_access->pf_seek = NoSeek; } p_access->pf_control = Control; p_access->p_sys = (void *)(intptr_t)fd; msg_Dbg( p_access, "file access output opened (%s)", p_access->psz_path ); if (append) lseek (fd, 0, SEEK_END); return VLC_SUCCESS; }
int fuse_valid_type(int m) { return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); }
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data_kernel data; struct ncp_server *server; struct file *ncp_filp; struct inode *root_inode; struct inode *sock_inode; struct socket *sock; int error; int default_bufsize; #ifdef CONFIG_NCPFS_PACKET_SIGNING int options; #endif struct ncp_entry_info finfo; memset(&data, 0, sizeof(data)); server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); if (!server) return -ENOMEM; sb->s_fs_info = server; error = -EFAULT; if (raw_data == NULL) goto out; switch (*(int*)raw_data) { case NCP_MOUNT_VERSION: { struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; data.flags = md->flags; data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = make_kuid(current_user_ns(), md->uid); data.gid = make_kgid(current_user_ns(), md->gid); data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd = -1; memcpy(data.mounted_vol, md->mounted_vol, NCP_VOLNAME_LEN+1); } break; case NCP_MOUNT_VERSION_V4: { struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; data.flags = md->flags; data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = make_kuid(current_user_ns(), md->uid); data.gid = make_kgid(current_user_ns(), md->gid); data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd = -1; } break; default: error = -ECHRNG; if (memcmp(raw_data, "vers", 4) == 0) { error = ncp_parse_options(&data, raw_data); } if (error) goto out; break; } error = -EINVAL; if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || !gid_valid(data.gid)) goto out; error = -EBADF; ncp_filp = fget(data.ncp_fd); if (!ncp_filp) goto out; error = -ENOTSOCK; sock_inode = file_inode(ncp_filp); if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput; sock = SOCKET_I(sock_inode); if (!sock) goto out_fput; if (sock->type == SOCK_STREAM) default_bufsize = 0xF000; else default_bufsize = 1024; sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ sb->s_maxbytes = 0xFFFFFFFFU; sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_op = &ncp_sops; sb->s_d_op = &ncp_dentry_operations; sb->s_bdi = &server->bdi; server = NCP_SBP(sb); memset(server, 0, sizeof(*server)); error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY); if (error) goto out_fput; server->ncp_filp = ncp_filp; server->ncp_sock = sock; if (data.info_fd != -1) { struct socket *info_sock; error = -EBADF; server->info_filp = fget(data.info_fd); if (!server->info_filp) goto out_bdi; error = -ENOTSOCK; sock_inode = file_inode(server->info_filp); if (!S_ISSOCK(sock_inode->i_mode)) goto out_fput2; info_sock = SOCKET_I(sock_inode); if (!info_sock) goto out_fput2; error = -EBADFD; if (info_sock->type != SOCK_STREAM) goto out_fput2; server->info_sock = info_sock; } /* server->lock = 0; */ mutex_init(&server->mutex); server->packet = NULL; /* server->buffer_size = 0; */ /* server->conn_status = 0; */ /* server->root_dentry = NULL; */ /* server->root_setuped = 0; */ mutex_init(&server->root_setup_lock); #ifdef CONFIG_NCPFS_PACKET_SIGNING /* server->sign_wanted = 0; */ /* server->sign_active = 0; */ #endif init_rwsem(&server->auth_rwsem); server->auth.auth_type = NCP_AUTH_NONE; /* server->auth.object_name_len = 0; */ /* server->auth.object_name = NULL; */ /* server->auth.object_type = 0; */ /* server->priv.len = 0; */ /* server->priv.data = NULL; */ server->m = data; /* Although anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 1) { server->m.time_out = 10; printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); } server->m.time_out = server->m.time_out * HZ / 100; server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR; #ifdef CONFIG_NCPFS_NLS /* load the default NLS charsets */ server->nls_vol = load_nls_default(); server->nls_io = load_nls_default(); #endif /* CONFIG_NCPFS_NLS */ atomic_set(&server->dentry_ttl, 0); /* no caching */ INIT_LIST_HEAD(&server->tx.requests); mutex_init(&server->rcv.creq_mutex); server->tx.creq = NULL; server->rcv.creq = NULL; init_timer(&server->timeout_tm); #undef NCP_PACKET_SIZE #define NCP_PACKET_SIZE 131072 error = -ENOMEM; server->packet_size = NCP_PACKET_SIZE; server->packet = vmalloc(NCP_PACKET_SIZE); if (server->packet == NULL) goto out_nls; server->txbuf = vmalloc(NCP_PACKET_SIZE); if (server->txbuf == NULL) goto out_packet; server->rxbuf = vmalloc(NCP_PACKET_SIZE); if (server->rxbuf == NULL) goto out_txbuf; lock_sock(sock->sk); server->data_ready = sock->sk->sk_data_ready; server->write_space = sock->sk->sk_write_space; server->error_report = sock->sk->sk_error_report; sock->sk->sk_user_data = server; sock->sk->sk_data_ready = ncp_tcp_data_ready; sock->sk->sk_error_report = ncp_tcp_error_report; if (sock->type == SOCK_STREAM) { server->rcv.ptr = (unsigned char*)&server->rcv.buf; server->rcv.len = 10; server->rcv.state = 0; INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc); INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc); sock->sk->sk_write_space = ncp_tcp_write_space; } else { INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc); INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc); server->timeout_tm.data = (unsigned long)server; server->timeout_tm.function = ncpdgram_timeout_call; } release_sock(sock->sk); ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); if (error < 0) goto out_rxbuf; DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ #ifdef CONFIG_NCPFS_PACKET_SIGNING if (ncp_negotiate_size_and_options(server, default_bufsize, NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) { if (options != NCP_DEFAULT_OPTIONS) { if (ncp_negotiate_size_and_options(server, default_bufsize, options & 2, &(server->buffer_size), &options) != 0) { goto out_disconnect; } } ncp_lock_server(server); if (options & 2) server->sign_wanted = 1; ncp_unlock_server(server); } else #endif /* CONFIG_NCPFS_PACKET_SIGNING */ if (ncp_negotiate_buffersize(server, default_bufsize, &(server->buffer_size)) != 0) goto out_disconnect; DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); memset(&finfo, 0, sizeof(finfo)); finfo.i.attributes = aDIR; finfo.i.dataStreamSize = 0; /* ignored */ finfo.i.dirEntNum = 0; finfo.i.DosDirNum = 0; #ifdef CONFIG_NCPFS_SMALLDOS finfo.i.NSCreator = NW_NS_DOS; #endif finfo.volume = NCP_NUMBER_OF_VOLUMES; /* set dates of mountpoint to Jan 1, 1986; 00:00 */ finfo.i.creationTime = finfo.i.modifyTime = cpu_to_le16(0x0000); finfo.i.creationDate = finfo.i.modifyDate = finfo.i.lastAccessDate = cpu_to_le16(0x0C21); finfo.i.nameLen = 0; finfo.i.entryName[0] = '\0'; finfo.opened = 0; finfo.ino = 2; /* tradition */ server->name_space[finfo.volume] = NW_NS_DOS; error = -ENOMEM; root_inode = ncp_iget(sb, &finfo); if (!root_inode) goto out_disconnect; DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); sb->s_root = d_make_root(root_inode); if (!sb->s_root) goto out_disconnect; return 0; out_disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); out_rxbuf: ncp_stop_tasks(server); vfree(server->rxbuf); out_txbuf: vfree(server->txbuf); out_packet: vfree(server->packet); out_nls: #ifdef CONFIG_NCPFS_NLS unload_nls(server->nls_io); unload_nls(server->nls_vol); #endif mutex_destroy(&server->rcv.creq_mutex); mutex_destroy(&server->root_setup_lock); mutex_destroy(&server->mutex); out_fput2: if (server->info_filp) fput(server->info_filp); out_bdi: bdi_destroy(&server->bdi); out_fput: /* 23/12/1998 Marcin Dalecki <*****@*****.**>: * * The previously used put_filp(ncp_filp); was bogus, since * it doesn't perform proper unlocking. */ fput(ncp_filp); out: put_pid(data.wdog_pid); sb->s_fs_info = NULL; kfree(server); return error; }
asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) { struct file *filp; struct inode *ino; struct strbuf __user *ctlptr; struct strbuf __user *datptr; struct strbuf ctl, dat; int __user *flgptr; int flags; int error = -EBADF; struct fdtable *fdt; SOLD("entry"); lock_kernel(); if(fd >= NR_OPEN) goto out; fdt = files_fdtable(current->files); filp = fdt->fd[fd]; if(!filp) goto out; ino = filp->f_dentry->d_inode; if (!ino || !S_ISSOCK(ino->i_mode)) goto out; ctlptr = (struct strbuf __user *)A(arg1); datptr = (struct strbuf __user *)A(arg2); flgptr = (int __user *)A(arg3); error = -EFAULT; if (ctlptr) { if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || put_user(-1,&ctlptr->len)) goto out; } else ctl.maxlen = -1; if (datptr) { if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || put_user(-1,&datptr->len)) goto out; } else dat.maxlen = -1; if (get_user(flags,flgptr)) goto out; switch (flags) { case 0: case MSG_HIPRI: case MSG_ANY: case MSG_BAND: break; default: error = -EINVAL; goto out; } error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len, A(dat.buf),dat.maxlen,&datptr->len,&flags); if (!error && put_user(flags,flgptr)) error = -EFAULT; out: unlock_kernel(); SOLD("done"); return error; }
C_Int_t Posix_FileSys_ST_isSock (C_Mode_t m) { return S_ISSOCK(m); }
/* * Create the file, or the directory * * fname is the original filename * ofile is the output filename (may be in a different directory) * * Returns: CF_SKIP if file should be skipped * CF_ERROR on error * CF_EXTRACT file created and data to restore * CF_CREATED file created no data to restore * * Note, we create the file here, except for special files, * we do not set the attributes because we want to first * write the file, then when the writing is done, set the * attributes. * So, we return with the file descriptor open for normal * files. * */ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) { mode_t new_mode, parent_mode; int flags; uid_t uid; gid_t gid; int pnl; bool exists = false; struct stat mstatp; bfd->reparse_point = false; if (is_win32_stream(attr->data_stream)) { set_win32_backup(bfd); } else { set_portable_backup(bfd); } new_mode = attr->statp.st_mode; Dmsg3(200, "type=%d newmode=%x file=%s\n", attr->type, new_mode, attr->ofname); parent_mode = S_IWUSR | S_IXUSR | new_mode; gid = attr->statp.st_gid; uid = attr->statp.st_uid; #ifdef HAVE_WIN32 if (!bfd->use_backup_api) { // eliminate invalid windows filename characters from foreign filenames char *ch = (char *)attr->ofname; if (ch[0] != 0 && ch[1] != 0) { ch += 2; while (*ch) { switch (*ch) { case ':': case '<': case '>': case '*': case '?': case '|': *ch = '_'; break; } ch++; } } } #endif Dmsg2(400, "Replace=%c %d\n", (char)replace, replace); if (lstat(attr->ofname, &mstatp) == 0) { exists = true; switch (replace) { case REPLACE_IFNEWER: if (attr->statp.st_mtime <= mstatp.st_mtime) { Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname); return CF_SKIP; } break; case REPLACE_IFOLDER: if (attr->statp.st_mtime >= mstatp.st_mtime) { Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname); return CF_SKIP; } break; case REPLACE_NEVER: Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname); return CF_SKIP; case REPLACE_ALWAYS: break; } } switch (attr->type) { case FT_RAW: /* raw device to be written */ case FT_FIFO: /* FIFO to be written to */ case FT_LNKSAVED: /* Hard linked, file already saved */ case FT_LNK: case FT_SPEC: /* fifo, ... to be backed up */ case FT_REGE: /* empty file */ case FT_REG: /* regular file */ /* * Note, we do not delete FT_RAW because these are device files * or FIFOs that should already exist. If we blow it away, * we may blow away a FIFO that is being used to read the * restore data, or we may blow away a partition definition. */ if (exists && attr->type != FT_RAW && attr->type != FT_FIFO) { /* Get rid of old copy */ Dmsg1(400, "unlink %s\n", attr->ofname); if (unlink(attr->ofname) == -1) { berrno be; Qmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"), attr->ofname, be.bstrerror()); /* Continue despite error */ } } /* * Here we do some preliminary work for all the above * types to create the path to the file if it does * not already exist. Below, we will split to * do the file type specific work */ pnl = separate_path_and_file(jcr, attr->fname, attr->ofname); if (pnl < 0) { return CF_ERROR; } /* * If path length is <= 0 we are making a file in the root * directory. Assume that the directory already exists. */ if (pnl > 0) { char savechr; savechr = attr->ofname[pnl]; attr->ofname[pnl] = 0; /* terminate path */ if (!path_already_seen(jcr, attr->ofname, pnl)) { Dmsg1(400, "Make path %s\n", attr->ofname); /* * If we need to make the directory, ensure that it is with * execute bit set (i.e. parent_mode), and preserve what already * exists. Normally, this should do nothing. */ if (!makepath(attr, attr->ofname, parent_mode, parent_mode, uid, gid, 1)) { Dmsg1(10, "Could not make path. %s\n", attr->ofname); attr->ofname[pnl] = savechr; /* restore full name */ return CF_ERROR; } } attr->ofname[pnl] = savechr; /* restore full name */ } /* Now we do the specific work for each file type */ switch(attr->type) { case FT_REGE: case FT_REG: Dmsg1(100, "Create=%s\n", attr->ofname); flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /* O_NOFOLLOW; */ if (IS_CTG(attr->statp.st_mode)) { flags |= O_CTG; /* set contiguous bit if needed */ } if (is_bopen(bfd)) { Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid); bclose(bfd); } if ((bopen(bfd, attr->ofname, flags, S_IRUSR | S_IWUSR)) < 0) { berrno be; be.set_errno(bfd->berrno); Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), attr->ofname, be.bstrerror()); Dmsg2(100,"Could not create %s: ERR=%s\n", attr->ofname, be.bstrerror()); return CF_ERROR; } return CF_EXTRACT; #ifndef HAVE_WIN32 // none of these exists on MS Windows case FT_RAW: /* Bacula raw device e.g. /dev/sda1 */ case FT_FIFO: /* Bacula fifo to save data */ case FT_SPEC: if (S_ISFIFO(attr->statp.st_mode)) { Dmsg1(400, "Restore fifo: %s\n", attr->ofname); if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) { berrno be; Qmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"), attr->ofname, be.bstrerror()); return CF_ERROR; } } else if (S_ISSOCK(attr->statp.st_mode)) { Dmsg1(200, "Skipping restore of socket: %s\n", attr->ofname); #ifdef S_IFDOOR // Solaris high speed RPC mechanism } else if (S_ISDOOR(attr->statp.st_mode)) { Dmsg1(200, "Skipping restore of door file: %s\n", attr->ofname); #endif #ifdef S_IFPORT // Solaris event port for handling AIO } else if (S_ISPORT(attr->statp.st_mode)) { Dmsg1(200, "Skipping restore of event port file: %s\n", attr->ofname); #endif } else { Dmsg1(400, "Restore node: %s\n", attr->ofname); if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) { berrno be; Qmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"), attr->ofname, be.bstrerror()); return CF_ERROR; } } /* * Here we are going to attempt to restore to a FIFO, which * means that the FIFO must already exist, AND there must * be some process already attempting to read from the * FIFO, so we open it write-only. */ if (attr->type == FT_RAW || attr->type == FT_FIFO) { btimer_t *tid; Dmsg1(400, "FT_RAW|FT_FIFO %s\n", attr->ofname); flags = O_WRONLY | O_BINARY; /* Timeout open() in 60 seconds */ if (attr->type == FT_FIFO) { Dmsg0(400, "Set FIFO timer\n"); tid = start_thread_timer(jcr, pthread_self(), 60); } else { tid = NULL; } if (is_bopen(bfd)) { Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid); } Dmsg2(400, "open %s flags=0x%x\n", attr->ofname, flags); if ((bopen(bfd, attr->ofname, flags, 0)) < 0) { berrno be; be.set_errno(bfd->berrno); Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), attr->ofname, be.bstrerror()); Dmsg2(400, "Could not open %s: ERR=%s\n", attr->ofname, be.bstrerror()); stop_thread_timer(tid); return CF_ERROR; } stop_thread_timer(tid); return CF_EXTRACT; } Dmsg1(400, "FT_SPEC %s\n", attr->ofname); return CF_CREATED; case FT_LNK: Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname); if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) { berrno be; Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"), attr->ofname, attr->olname, be.bstrerror()); return CF_ERROR; } return CF_CREATED; case FT_LNKSAVED: /* Hard linked, file already saved */ Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname); if (link(attr->olname, attr->ofname) != 0) { berrno be; #ifdef HAVE_CHFLAGS struct stat s; /* * If using BSD user flags, maybe has a file flag * preventing this. So attempt to disable, retry link, * and reset flags. * Note that BSD securelevel may prevent disabling flag. */ if (stat(attr->olname, &s) == 0 && s.st_flags != 0) { if (chflags(attr->olname, 0) == 0) { if (link(attr->olname, attr->ofname) != 0) { /* restore original file flags even when linking failed */ if (chflags(attr->olname, s.st_flags) < 0) { Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"), attr->olname, be.bstrerror()); } #endif /* HAVE_CHFLAGS */ Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"), attr->ofname, attr->olname, be.bstrerror()); Dmsg3(200, "Could not hard link %s -> %s: ERR=%s\n", attr->ofname, attr->olname, be.bstrerror()); return CF_ERROR; #ifdef HAVE_CHFLAGS } /* finally restore original file flags */ if (chflags(attr->olname, s.st_flags) < 0) { Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"), attr->olname, be.bstrerror()); } } else { Qmsg2(jcr, M_ERROR, 0, _("Could not reset file flags for file %s: ERR=%s\n"), attr->olname, be.bstrerror()); } } else { Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"), attr->ofname, attr->olname, be.bstrerror()); return CF_ERROR; } #endif /* HAVE_CHFLAGS */ } return CF_CREATED; #endif } /* End inner switch */ case FT_REPARSE: bfd->reparse_point = true; /* Fall through wanted */ case FT_DIRBEGIN: case FT_DIREND: Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname); if (!makepath(attr, attr->ofname, new_mode, parent_mode, uid, gid, 0)) { return CF_ERROR; } /* * If we are using the Win32 Backup API, we open the * directory so that the security info will be read * and saved. */ if (!is_portable_backup(bfd)) { if (is_bopen(bfd)) { Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid); } if ((bopen(bfd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) { berrno be; be.set_errno(bfd->berrno); #ifdef HAVE_WIN32 /* Check for trying to create a drive, if so, skip */ if (attr->ofname[1] == ':' && IsPathSeparator(attr->ofname[2]) && attr->ofname[3] == '\0') { return CF_SKIP; } #endif Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), attr->ofname, be.bstrerror()); return CF_ERROR; } return CF_EXTRACT; } else { return CF_CREATED; } case FT_DELETED: Qmsg2(jcr, M_INFO, 0, _("Original file %s have been deleted: type=%d\n"), attr->fname, attr->type); break; /* The following should not occur */ case FT_NOACCESS: case FT_NOFOLLOW: case FT_NOSTAT: case FT_DIRNOCHG: case FT_NOCHG: case FT_ISARCH: case FT_NORECURSE: case FT_NOFSCHG: case FT_NOOPEN: Qmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type); break; default: Qmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname); break; } return CF_ERROR; }
static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd, struct vma_file_info *vfi, struct vma_file_info *prev_vfi) { char path[32]; if (prev_vfi->vma && vfi_equal(vfi, prev_vfi)) { struct vma_area *prev = prev_vfi->vma; /* * If vfi is equal (!) and negative @vm_file_fd -- * we have nothing to borrow for sure. */ if (prev->vm_file_fd < 0) return 0; pr_debug("vma %"PRIx64" borrows vfi from previous %"PRIx64"\n", vma->e->start, prev->e->start); vma->vm_file_fd = prev->vm_file_fd; if (prev->e->status & VMA_AREA_SOCKET) vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR; /* * FIXME -- in theory there can be vmas that have * dev:ino match, but live in different mount * namespaces. However, we only borrow files for * subsequent vmas. These are _very_ likely to * have files from the same namespaces. */ vma->file_borrowed = true; return 0; } /* Figure out if it's file mapping */ snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end); /* * Note that we "open" it in dumper process space * so later we might refer to it via /proc/self/fd/vm_file_fd * if needed. */ vma->vm_file_fd = openat(dirfd(mfd), path, O_RDONLY); if (vma->vm_file_fd < 0) { if (errno == ENOENT) /* Just mapping w/o map_files link */ return 0; if (errno == ENXIO) { struct stat buf; if (fstatat(dirfd(mfd), path, &buf, 0)) return -1; if (S_ISSOCK(buf.st_mode)) { pr_info("Found socket mapping @%"PRIx64"\n", vma->e->start); vma->vm_socket_id = buf.st_ino; vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR; return 0; } if ((buf.st_mode & S_IFMT) == 0 && !strcmp(fname, AIO_FNAME)) { /* AIO ring, let's try */ close(vma->vm_file_fd); vma->aio_nr_req = -1; vma->e->status = VMA_AREA_AIORING; return 0; } pr_err("Unknown shit %o (%s)\n", buf.st_mode, fname); } return -1; } vma->vmst = xmalloc(sizeof(struct stat)); if (!vma->vmst) return -1; /* * For AUFS support, we need to check if the symbolic link * points to a branch. If it does, we cannot fstat() its file * descriptor because it would return a different dev/ino than * the real file. If fixup_aufs_vma_fd() returns positive, * it means that it has stat()'ed using the full pathname. * Zero return means that the symbolic link does not point to * a branch and we can do fstat() below. */ if (opts.aufs) { int ret; ret = fixup_aufs_vma_fd(vma); if (ret < 0) return -1; if (ret > 0) return 0; } if (fstat(vma->vm_file_fd, vma->vmst) < 0) { pr_perror("Failed fstat on map %"PRIx64"", vma->e->start); return -1; } return 0; }
/* Return: * -1 error, copy not made * 0 copy is made or user answered "no" in interactive mode * (failures to preserve mode/owner/times are not reported in exit code) */ int copy_file(const char *source, const char *dest, int flags) { /* This is a recursive function, try to minimize stack usage */ /* NB: each struct stat is ~100 bytes */ struct stat source_stat; struct stat dest_stat; signed char retval = 0; signed char dest_exists = 0; signed char ovr; /* Inverse of cp -d ("cp without -d") */ #define FLAGS_DEREF (flags & FILEUTILS_DEREFERENCE) if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) { // This may be a dangling symlink. // Making [sym]links to dangling symlinks works, so... if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) goto make_links; bb_perror_msg("cannot stat '%s'", source); return -1; } if (lstat(dest, &dest_stat) < 0) { if (errno != ENOENT) { bb_perror_msg("cannot stat '%s'", dest); return -1; } } else { if (source_stat.st_dev == dest_stat.st_dev && source_stat.st_ino == dest_stat.st_ino ) { bb_error_msg("'%s' and '%s' are the same file", source, dest); return -1; } dest_exists = 1; } #if ENABLE_SELINUX if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) { security_context_t con; if (lgetfilecon(source, &con) >= 0) { if (setfscreatecon(con) < 0) { bb_perror_msg("cannot set setfscreatecon %s", con); freecon(con); return -1; } } else if (errno == ENOTSUP || errno == ENODATA) { setfscreatecon_or_die(NULL); } else { bb_perror_msg("cannot lgetfilecon %s", source); return -1; } } #endif if (S_ISDIR(source_stat.st_mode)) { DIR *dp; const char *tp; struct dirent *d; mode_t saved_umask = 0; if (!(flags & FILEUTILS_RECUR)) { bb_error_msg("omitting directory '%s'", source); return -1; } /* Did we ever create source ourself before? */ tp = is_in_ino_dev_hashtable(&source_stat); if (tp) { /* We did! it's a recursion! man the lifeboats... */ bb_error_msg("recursion detected, omitting directory '%s'", source); return -1; } /* Create DEST */ if (dest_exists) { if (!S_ISDIR(dest_stat.st_mode)) { bb_error_msg("target '%s' is not a directory", dest); return -1; } /* race here: user can substitute a symlink between * this check and actual creation of files inside dest */ } else { mode_t mode; saved_umask = umask(0); mode = source_stat.st_mode; if (!(flags & FILEUTILS_PRESERVE_STATUS)) mode = source_stat.st_mode & ~saved_umask; /* Allow owner to access new dir (at least for now) */ mode |= S_IRWXU; if (mkdir(dest, mode) < 0) { umask(saved_umask); bb_perror_msg("cannot create directory '%s'", dest); return -1; } umask(saved_umask); /* need stat info for add_to_ino_dev_hashtable */ if (lstat(dest, &dest_stat) < 0) { bb_perror_msg("cannot stat '%s'", dest); return -1; } } /* remember (dev,inode) of each created dir. * NULL: name is not remembered */ add_to_ino_dev_hashtable(&dest_stat, NULL); /* Recursively copy files in SOURCE */ dp = opendir(source); if (dp == NULL) { retval = -1; goto preserve_mode_ugid_time; } while ((d = readdir(dp)) != NULL) { char *new_source, *new_dest; new_source = concat_subpath_file(source, d->d_name); if (new_source == NULL) continue; new_dest = concat_path_file(dest, d->d_name); if (copy_file(new_source, new_dest, flags) < 0) retval = -1; free(new_source); free(new_dest); } closedir(dp); if (!dest_exists && chmod(dest, source_stat.st_mode & ~saved_umask) < 0 ) { bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest); /* retval = -1; - WRONG! copy *WAS* made */ } goto preserve_mode_ugid_time; } if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { int (*lf)(const char *oldpath, const char *newpath); make_links: // Hmm... maybe // if (DEREF && MAKE_SOFTLINK) source = realpath(source) ? // (but realpath returns NULL on dangling symlinks...) lf = (flags & FILEUTILS_MAKE_SOFTLINK) ? symlink : link; if (lf(source, dest) < 0) { ovr = ask_and_unlink(dest, flags); if (ovr <= 0) return ovr; if (lf(source, dest) < 0) { bb_perror_msg("cannot create link '%s'", dest); return -1; } } /* _Not_ jumping to preserve_mode_ugid_time: * hard/softlinks don't have those */ return 0; } if (/* "cp thing1 thing2" without -R: just open and read() from thing1 */ !(flags & FILEUTILS_RECUR) /* "cp [-opts] regular_file thing2" */ || S_ISREG(source_stat.st_mode) /* DEREF uses stat, which never returns S_ISLNK() == true. * So the below is never true: */ /* || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) */ ) { int src_fd; int dst_fd; mode_t new_mode; if (!FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) { /* "cp -d symlink dst": create a link */ goto dont_cat; } if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) { const char *link_target; link_target = is_in_ino_dev_hashtable(&source_stat); if (link_target) { if (link(link_target, dest) < 0) { ovr = ask_and_unlink(dest, flags); if (ovr <= 0) return ovr; if (link(link_target, dest) < 0) { bb_perror_msg("cannot create link '%s'", dest); return -1; } } return 0; } add_to_ino_dev_hashtable(&source_stat, dest); } src_fd = open_or_warn(source, O_RDONLY); if (src_fd < 0) return -1; /* Do not try to open with weird mode fields */ new_mode = source_stat.st_mode; if (!S_ISREG(source_stat.st_mode)) new_mode = 0666; /* POSIX way is a security problem versus symlink attacks, * we do it only for non-symlinks, and only for non-recursive, * non-interactive cp. NB: it is still racy * for "cp file /home/bad_user/file" case * (user can rm file and create a link to /etc/passwd) */ if (DO_POSIX_CP || (dest_exists && !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE)) && !S_ISLNK(dest_stat.st_mode)) ) { dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); } else /* safe way: */ dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); if (dst_fd == -1) { ovr = ask_and_unlink(dest, flags); if (ovr <= 0) { close(src_fd); return ovr; } /* It shouldn't exist. If it exists, do not open (symlink attack?) */ dst_fd = open3_or_warn(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); if (dst_fd < 0) { close(src_fd); return -1; } } #if ENABLE_SELINUX if ((flags & (FILEUTILS_PRESERVE_SECURITY_CONTEXT|FILEUTILS_SET_SECURITY_CONTEXT)) && is_selinux_enabled() > 0 ) { security_context_t con; if (getfscreatecon(&con) == -1) { bb_perror_msg("getfscreatecon"); return -1; } if (con) { if (setfilecon(dest, con) == -1) { bb_perror_msg("setfilecon:%s,%s", dest, con); freecon(con); return -1; } freecon(con); } } #endif if (bb_copyfd_eof(src_fd, dst_fd) == -1) retval = -1; /* Ok, writing side I can understand... */ if (close(dst_fd) < 0) { bb_perror_msg("cannot close '%s'", dest); retval = -1; } /* ...but read size is already checked by bb_copyfd_eof */ close(src_fd); /* "cp /dev/something new_file" should not * copy mode of /dev/something */ if (!S_ISREG(source_stat.st_mode)) return retval; goto preserve_mode_ugid_time; } dont_cat: /* Source is a symlink or a special file */ /* We are lazy here, a bit lax with races... */ if (dest_exists) { errno = EEXIST; ovr = ask_and_unlink(dest, flags); if (ovr <= 0) return ovr; } if (S_ISLNK(source_stat.st_mode)) { char *lpath = xmalloc_readlink_or_warn(source); if (lpath) { int r = symlink(lpath, dest); free(lpath); if (r < 0) { bb_perror_msg("cannot create symlink '%s'", dest); return -1; } if (flags & FILEUTILS_PRESERVE_STATUS) if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0) bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest); } /* _Not_ jumping to preserve_mode_ugid_time: * symlinks don't have those */ return 0; } if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) ) { if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) { bb_perror_msg("cannot create '%s'", dest); return -1; } } else { bb_error_msg("unrecognized file '%s' with mode %x", source, source_stat.st_mode); return -1; } preserve_mode_ugid_time: if (flags & FILEUTILS_PRESERVE_STATUS /* Cannot happen: */ /* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */ ) { struct utimbuf times; times.actime = source_stat.st_atime; times.modtime = source_stat.st_mtime; /* BTW, utimes sets usec-precision time - just FYI */ if (utime(dest, ×) < 0) bb_perror_msg("cannot preserve %s of '%s'", "times", dest); if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) { source_stat.st_mode &= ~(S_ISUID | S_ISGID); bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest); } if (chmod(dest, source_stat.st_mode) < 0) bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest); } return retval; }
/* * Add the file or dir hierarchy named by 'path' to the archive */ static void write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) { struct archive_entry *entry = NULL, *spare_entry = NULL; struct tree *tree; char symlink_mode = bsdtar->symlink_mode; dev_t first_dev = 0; int dev_recorded = 0; int tree_ret; dev_t last_dev = 0; char * fstype; tree = tree_open(path); if (!tree) { bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path); bsdtar->return_value = 1; return; } while ((tree_ret = tree_next(tree))) { int r; const char *name = tree_current_path(tree); const struct stat *st = NULL; /* info to use for this entry */ const struct stat *lst = NULL; /* lstat() information */ int descend; if (truncate_archive(bsdtar)) break; if (checkpoint_archive(bsdtar, 0)) exit(1); disk_pause(bsdtar); if (network_select(0)) exit(1); if (tree_ret == TREE_ERROR_FATAL) bsdtar_errc(bsdtar, 1, tree_errno(tree), "%s: Unable to continue traversing directory tree", name); if (tree_ret == TREE_ERROR_DIR) { bsdtar_warnc(bsdtar, errno, "%s: Couldn't visit directory", name); bsdtar->return_value = 1; } if (tree_ret != TREE_REGULAR) continue; /* * If this file/dir is excluded by a filename * pattern, skip it. */ if (excluded(bsdtar, name)) continue; /* * Get lstat() info from the tree library. */ lst = tree_current_lstat(tree); if (lst == NULL) { /* Couldn't lstat(); must not exist. */ bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name); /* Return error if files disappear during traverse. */ bsdtar->return_value = 1; continue; } /* * Distinguish 'L'/'P'/'H' symlink following. */ switch(symlink_mode) { case 'H': /* 'H': After the first item, rest like 'P'. */ symlink_mode = 'P'; /* 'H': First item (from command line) like 'L'. */ /* FALLTHROUGH */ case 'L': /* 'L': Do descend through a symlink to dir. */ descend = tree_current_is_dir(tree); /* 'L': Follow symlinks to files. */ archive_read_disk_set_symlink_logical(bsdtar->diskreader); /* 'L': Archive symlinks as targets, if we can. */ st = tree_current_stat(tree); if (st != NULL) break; /* If stat fails, we have a broken symlink; * in that case, don't follow the link. */ /* FALLTHROUGH */ default: /* 'P': Don't descend through a symlink to dir. */ descend = tree_current_is_physical_dir(tree); /* 'P': Don't follow symlinks to files. */ archive_read_disk_set_symlink_physical(bsdtar->diskreader); /* 'P': Archive symlinks as symlinks. */ st = lst; break; } if (bsdtar->option_no_subdirs) descend = 0; /* * If user has asked us not to cross mount points, * then don't descend into a dir on a different * device. */ if (!dev_recorded) { last_dev = first_dev = lst->st_dev; dev_recorded = 1; } if (bsdtar->option_dont_traverse_mounts) { if (lst->st_dev != first_dev) descend = 0; } /* * If the user did not specify --insane-filesystems, do not * cross into a new filesystem which is known to be synthetic. * Note that we will archive synthetic filesystems if we are * explicitly told to do so. */ if ((bsdtar->option_insane_filesystems == 0) && (descend != 0) && (lst->st_dev != last_dev)) { fstype = getfstype(tree_current_access_path(tree)); if (fstype == NULL) bsdtar_errc(bsdtar, 1, errno, "%s: Error getting filesystem type", name); if (getfstype_issynthetic(fstype)) { if (!bsdtar->option_quiet) bsdtar_warnc(bsdtar, 0, "Not descending into filesystem of type %s: %s", fstype, name); descend = 0; } else { /* This device is ok to archive. */ last_dev = lst->st_dev; } free(fstype); } /* * In -u mode, check that the file is newer than what's * already in the archive; in all modes, obey --newerXXX flags. */ if (!new_enough(bsdtar, name, st)) { if (!descend) continue; if (bsdtar->option_interactive && !yes("add '%s'", name)) continue; tree_descend(tree); continue; } archive_entry_free(entry); entry = archive_entry_new(); archive_entry_set_pathname(entry, name); archive_entry_copy_sourcepath(entry, tree_current_access_path(tree)); /* Populate the archive_entry with metadata from the disk. */ /* XXX TODO: Arrange to open a regular file before * calling this so we can pass in an fd and shorten * the race to query metadata. The linkify dance * makes this more complex than it might sound. */ r = archive_read_disk_entry_from_file(bsdtar->diskreader, entry, -1, st); if (r != ARCHIVE_OK) bsdtar_warnc(bsdtar, archive_errno(bsdtar->diskreader), "%s", archive_error_string(bsdtar->diskreader)); if (r < ARCHIVE_WARN) continue; /* XXX TODO: Just use flag data from entry; avoid the * duplicate check here. */ /* * If this file/dir is flagged "nodump" and we're * honoring such flags, skip this file/dir. */ #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) /* BSD systems store flags in struct stat */ if (bsdtar->option_honor_nodump && (lst->st_flags & UF_NODUMP)) continue; #endif #if defined(EXT2_NODUMP_FL) /* Linux uses ioctl to read flags. */ if (bsdtar->option_honor_nodump) { unsigned long fflags, dummy; archive_entry_fflags(entry, &fflags, &dummy); if (fflags & EXT2_NODUMP_FL) continue; } #endif /* * Don't back up the cache directory or any files inside it. */ if ((lst->st_ino == bsdtar->cachedir_ino) && (lst->st_dev == bsdtar->cachedir_dev)) { if (!bsdtar->option_quiet) bsdtar_warnc(bsdtar, 0, "Not adding cache directory to archive: %s", name); continue; } /* * If the user vetoes this file/directory, skip it. * We want this to be fairly late; if some other * check would veto this file, we shouldn't bother * the user with it. */ if (bsdtar->option_interactive && !yes("add '%s'", name)) continue; /* Note: if user vetoes, we won't descend. */ if (descend) tree_descend(tree); /* * Rewrite the pathname to be archived. If rewrite * fails, skip the entry. */ if (edit_pathname(bsdtar, entry)) continue; /* * If this is a socket, skip the entry: POSIX requires that * pax(1) emit a "diagnostic message" (i.e., warning) that * sockets cannot be archived, but this can make backups of * running systems very noisy. */ if (S_ISSOCK(st->st_mode)) continue; /* Display entry as we process it. * This format is required by SUSv2. */ if (bsdtar->verbose) safe_fprintf(stderr, "a %s", archive_entry_pathname(entry)); /* * If the user hasn't specifically asked to have the access * time stored, zero it. At the moment this usually only * matters for files which have flags set, since the "posix * restricted" format doesn't store access times for most * other files. */ if (bsdtar->option_store_atime == 0) archive_entry_set_atime(entry, 0, 0); /* Non-regular files get archived with zero size. */ if (!S_ISREG(st->st_mode)) archive_entry_set_size(entry, 0); /* Record what we're doing, for SIGINFO / SIGUSR1. */ siginfo_setinfo(bsdtar, "adding", archive_entry_pathname(entry), archive_entry_size(entry)); archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry); /* Handle SIGINFO / SIGUSR1 request if one was made. */ siginfo_printinfo(bsdtar, 0); while (entry != NULL) { write_entry_backend(bsdtar, a, entry, st, tree_current_realpath(tree)); archive_entry_free(entry); entry = spare_entry; spare_entry = NULL; } if (bsdtar->verbose) fprintf(stderr, "\n"); } archive_entry_free(entry); if (tree_close(tree)) bsdtar_errc(bsdtar, 1, 0, "Error traversing directory tree"); }
VistaIOBoolean VistaIOIdentifyFiles (int noptions, VistaIOOptionDescRec options[], VistaIOStringConst keyword, int *argc, char **argv, int fd) { VistaIOOptionDescRec *opt; VistaIOArgVector *vec; VistaIOBoolean switch_found = FALSE; VistaIOStringConst *values; struct stat stat_buf; int i, j, n; /* A -in or -out switch on the command line may specify one or more files. Look for the switch's entry in the option table supplied: */ for (i = 0, opt = options; i < noptions; i++, opt++) if (strcmp (keyword, opt->keyword) == 0) break; if (i == noptions) VistaIOError ("VistaIOIdentifyFiles: Option -%s not defined in option table", keyword); /* The option table entry must specify a location for storing filenames: */ if (!opt->value) VistaIOError ("VistaIOIdentifyFiles: No value storage for option -%s", keyword); vec = ((VistaIOArgVector *) opt->value); /* Whether or not the option was present on the command line should have been recorded in a "found" flag: */ if (opt->found && opt->found != VistaIORequiredOpt && opt->found != VistaIOOptionalOpt) switch_found = *(opt->found); else VistaIOError ("VistaIOIdentifyFiles: No \"found\" flag for option -%s", keyword); /* If a -in or -out switch was specified, it supplies the files' names: */ if (switch_found) return TRUE; /* If no switch was specified but some extra arguments were supplied with the command, those arguments should be the files' names: */ if (*argc > 1) { /* If any number are permitted, allocate storage for all of them: */ if (opt->number == 0) { vec->vector = VistaIOMalloc ((*argc - 1) * sizeof (VistaIOStringConst)); values = (VistaIOStringConst *) vec->vector; } else values = (VistaIOStringConst *) opt->value; /* Accept arguments as filenames provided they don't begin with a single -: */ for (i = j = 1, n = 0; i < *argc; i++) if ((argv[i][0] == '-' && argv[i][1] != '-') || (opt->number && n == opt->number)) argv[j++] = argv[i]; /* not a filename */ else if (argv[i][0] == '-' && argv[i][1] == '-') values[n++] = argv[i] + 1; /* filename with -- prefix */ else values[n++] = argv[i]; /* filename */ /* Ensure that a sufficient number were supplied: */ if (n) { if (opt->number) { if (n != opt->number) { if (opt->number == 1) { goto WrongNumber1; } else { goto WrongNumberN; } } } else vec->number = n; *argc = j; return TRUE; } } /* That leaves only an open file descriptor as the file. In that case there can be at most one such file: */ if (opt->number > 1) { WrongNumberN: fprintf (stderr, "%s: %d files must be specified by -%s or " "extra command arguments.\n", argv[0], opt->number, keyword); return FALSE; } /* If a particular file descriptor is specified by fd, ensure that it is connected to a pipe or file (not the terminal): */ if (fd >= 0) { if (fstat (fd, &stat_buf) == -1) VistaIOSystemError ("Failed to fstat() fd %d", fd); if (!S_ISREG (stat_buf.st_mode) #ifdef S_ISSOCK /* The ISSOCK macro is only available in POSIX_STDC; beware of problems with piping files if this line is omited */ && !S_ISSOCK (stat_buf.st_mode) #endif && !S_ISLNK (stat_buf.st_mode) && !S_ISFIFO (stat_buf.st_mode)) { WrongNumber1: fprintf (stderr, "%s: No file specified by -%s, extra command " "argument, or %c.\n", argv[0], keyword, "<>"[fd]); return FALSE; } } /* Record the file as being "-": */ if (opt->number == 0) { vec->number = 1; vec->vector = VistaIOMalloc (sizeof (VistaIOStringConst)); ((VistaIOStringConst *) vec->vector)[0] = "-"; } else *((VistaIOStringConst *) opt->value) = "-"; return TRUE; }
int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev) { struct kevent kev[2]; uint16_t flags; int e; if ((!ev && op != EPOLL_CTL_DEL) || (ev && ((ev->events & ~(EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP | EPOLLERR)) /* the user should really set one of EPOLLIN or EPOLLOUT * so that EPOLLHUP and EPOLLERR work. Don't make this a * hard error for now, though. */ /* || !(ev->events & (EPOLLIN | EPOLLOUT)) */))) { errno = EINVAL; return (-1); } if (fd2 < 0 || ((uint32_t)fd2 & ~(((uint32_t)1 << KEY_BITS) - 1))) { errno = EBADF; return (-1); } if ((e = kqueue_load_state(fd, fd2, &flags)) < 0) { errno = e; return (-1); } if (op == EPOLL_CTL_ADD) { if (flags & KQUEUE_STATE_REGISTERED) { errno = EEXIST; return (-1); } EV_SET(&kev[0], fd2, EVFILT_READ, EV_ADD | (ev->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, ev->data.ptr); EV_SET(&kev[1], fd2, EVFILT_WRITE, EV_ADD | (ev->events & EPOLLOUT ? 0 : EV_DISABLE), 0, 0, ev->data.ptr); flags = KQUEUE_STATE_REGISTERED; #define SET_FLAG(flag) \ do { \ if (ev->events & (flag)) { \ flags |= KQUEUE_STATE_##flag; \ } \ } while (0) SET_FLAG(EPOLLIN); SET_FLAG(EPOLLOUT); SET_FLAG(EPOLLRDHUP); #undef SET_FLAG } else if (op == EPOLL_CTL_DEL) { if (poll_fd == fd2 && fd == poll_epoll_fd) { poll_fd = -1; poll_epoll_fd = -1; poll_ptr = NULL; return 0; } if (!(flags & KQUEUE_STATE_REGISTERED)) { errno = ENOENT; return (-1); } EV_SET(&kev[0], fd2, EVFILT_READ, EV_DELETE, 0, 0, 0); EV_SET(&kev[1], fd2, EVFILT_WRITE, EV_DELETE, 0, 0, 0); flags = 0; } else if (op == EPOLL_CTL_MOD) { if (!(flags & KQUEUE_STATE_REGISTERED)) { errno = ENOENT; return (-1); } EV_SET(&kev[0], fd2, EVFILT_READ, ev->events & EPOLLIN ? EV_ENABLE : EV_DISABLE, 0, 0, ev->data.ptr); EV_SET(&kev[1], fd2, EVFILT_WRITE, ev->events & EPOLLOUT ? EV_ENABLE : EV_DISABLE, 0, 0, ev->data.ptr); #define SET_FLAG(flag) \ do { \ if (ev->events & (flag)) { \ flags |= KQUEUE_STATE_##flag; \ } else { \ flags &= ~KQUEUE_STATE_##flag; \ } \ } while (0) SET_FLAG(EPOLLIN); SET_FLAG(EPOLLOUT); SET_FLAG(EPOLLRDHUP); #undef SET_FLAG } else { errno = EINVAL; return (-1); } for (int i = 0; i < 2; ++i) { kev[i].flags |= EV_RECEIPT; } int ret = kevent(fd, kev, 2, kev, 2, NULL); if (ret < 0) { return -1; } if (ret != 2) { errno = EINVAL; return -1; } for (int i = 0; i < 2; ++i) { if (!(kev[i].flags & EV_ERROR)) { errno = EINVAL; return -1; } if (kev[i].data == ENODEV && poll_fd < 0) { poll_fd = fd2; poll_epoll_fd = fd; poll_ptr = ev->data.ptr; return 0; } /* * Ignore EVFILT_WRITE registration EINVAL errors (some fd * types such as kqueues themselves don't support it). * Also ignore ENOENT -- this happens when trying to remove a * previously added fd where the EVFILT_WRITE registration * failed. */ if (i == 1 && (kev[i].data == EINVAL || kev[i].data == ENOENT)) { continue; } if (kev[i].data != 0) { errno = kev[i].data; return -1; } } if (op != EPOLL_CTL_DEL && is_not_yet_connected_stream_socket(fd2)) { EV_SET(&kev[0], fd2, EVFILT_READ, EV_ENABLE | EV_FORCEONESHOT, 0, 0, ev->data.ptr); if (kevent(fd, kev, 1, NULL, 0, NULL) < 0) { return -1; } flags |= KQUEUE_STATE_NYCSS; } struct stat statbuf; if (fstat(fd2, &statbuf) < 0) { return -1; } if (S_ISFIFO(statbuf.st_mode)) { flags |= KQUEUE_STATE_ISFIFO; } else if (S_ISSOCK(statbuf.st_mode)) { flags |= KQUEUE_STATE_ISSOCK; } if ((e = kqueue_save_state(fd, fd2, flags)) < 0) { errno = e; return (-1); } return 0; }
struct device * ether_Create(struct physical *p) { u_char rbuf[2048]; struct etherdevice *dev; struct ng_mesg *resp; const struct hooklist *hlist; const struct nodeinfo *ninfo; char *path, *sessionid; int ifacelen, f; dev = NULL; path = NULL; ifacelen = 0; if (p->fd < 0 && !strncasecmp(p->name.full, NG_PPPOE_NODE_TYPE, PPPOE_NODE_TYPE_LEN) && p->name.full[PPPOE_NODE_TYPE_LEN] == ':') { const struct linkinfo *nlink; struct ngpppoe_init_data *data; struct ngm_mkpeer mkp; struct ngm_connect ngc; const char *iface, *provider; char etherid[12]; int providerlen; char connectpath[sizeof dev->hook + 2]; /* .:<hook> */ p->fd--; /* We own the device - change fd */ loadmodules(LOAD_VERBOSLY, "netgraph", "ng_ether", "ng_pppoe", "ng_socket", NULL); if ((dev = malloc(sizeof *dev)) == NULL) return NULL; iface = p->name.full + PPPOE_NODE_TYPE_LEN + 1; provider = strchr(iface, ':'); if (provider) { ifacelen = provider - iface; provider++; providerlen = strlen(provider); } else { ifacelen = strlen(iface); provider = ""; providerlen = 0; } /* * We're going to do this (where tunN is our tunnel device): * * .---------. * | ether | * | <iface> | dev->cs * `---------' | * (orphan) p->fd | * | | | * | | | * (ethernet) | | * .---------. .-----------. * | pppoe | | socket | * | <iface> |(tunN)<---->(tunN)| <unnamed> | * `--------- `-----------' * (tunX) * ^ * | * `--->(tunX) */ /* Create a socket node */ if (ID0NgMkSockNode(NULL, &dev->cs, &p->fd) == -1) { log_Printf(LogWARN, "Cannot create netgraph socket node: %s\n", strerror(errno)); free(dev); p->fd = -2; return NULL; } /* * Ask for a list of hooks attached to the "ether" node. This node should * magically exist as a way of hooking stuff onto an ethernet device */ path = (char *)alloca(ifacelen + 2); snprintf(path, ifacelen + 2, "%.*s:", ifacelen, iface); if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, NULL, 0) < 0) { log_Printf(LogWARN, "%s Cannot send a netgraph message: %s\n", path, strerror(errno)); return ether_Abandon(dev, p); } /* Get our list back */ resp = (struct ng_mesg *)rbuf; if (NgRecvMsg(dev->cs, resp, sizeof rbuf, NULL) <= 0) { log_Printf(LogWARN, "Cannot get netgraph response: %s\n", strerror(errno)); return ether_Abandon(dev, p); } hlist = (const struct hooklist *)resp->data; ninfo = &hlist->nodeinfo; /* Make sure we've got the right type of node */ if (strncmp(ninfo->type, NG_ETHER_NODE_TYPE, sizeof NG_ETHER_NODE_TYPE - 1)) { log_Printf(LogWARN, "%s Unexpected node type ``%s'' (wanted ``" NG_ETHER_NODE_TYPE "'')\n", path, ninfo->type); return ether_Abandon(dev, p); } log_Printf(LogDEBUG, "List of netgraph node ``%s'' (id %x) hooks:\n", path, ninfo->id); /* look for a hook already attached. */ for (f = 0; f < ninfo->hooks; f++) { nlink = &hlist->link[f]; log_Printf(LogDEBUG, " Found %s -> %s\n", nlink->ourhook, nlink->peerhook); if (!strcmp(nlink->ourhook, NG_ETHER_HOOK_ORPHAN) || !strcmp(nlink->ourhook, NG_ETHER_HOOK_DIVERT)) { /* * Something is using the data coming out of this ``ether'' node. * If it's a PPPoE node, we use that node, otherwise we complain that * someone else is using the node. */ if (!strcmp(nlink->nodeinfo.type, NG_PPPOE_NODE_TYPE)) /* Use this PPPoE node ! */ snprintf(ngc.path, sizeof ngc.path, "[%x]:", nlink->nodeinfo.id); else { log_Printf(LogWARN, "%s Node type ``%s'' is currently active\n", path, nlink->nodeinfo.type); return ether_Abandon(dev, p); } break; } } if (f == ninfo->hooks) { /* * Create a new ``PPPoE'' node connected to the ``ether'' node using * the ``orphan'' and ``ethernet'' hooks */ snprintf(mkp.type, sizeof mkp.type, "%s", NG_PPPOE_NODE_TYPE); snprintf(mkp.ourhook, sizeof mkp.ourhook, "%s", NG_ETHER_HOOK_ORPHAN); snprintf(mkp.peerhook, sizeof mkp.peerhook, "%s", NG_PPPOE_HOOK_ETHERNET); snprintf(etherid, sizeof etherid, "[%x]:", ninfo->id); log_Printf(LogDEBUG, "Creating PPPoE netgraph node %s%s -> %s\n", etherid, mkp.ourhook, mkp.peerhook); if (NgSendMsg(dev->cs, etherid, NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp, sizeof mkp) < 0) { log_Printf(LogWARN, "%s Cannot create PPPoE netgraph node: %s\n", etherid, strerror(errno)); return ether_Abandon(dev, p); } snprintf(ngc.path, sizeof ngc.path, "%s%s", path, NG_ETHER_HOOK_ORPHAN); } snprintf(dev->hook, sizeof dev->hook, "%s%d", TUN_NAME, p->dl->bundle->unit); /* * Connect the PPPoE node to our socket node. * ngc.path has already been set up */ snprintf(ngc.ourhook, sizeof ngc.ourhook, "%s", dev->hook); memcpy(ngc.peerhook, ngc.ourhook, sizeof ngc.peerhook); log_Printf(LogDEBUG, "Connecting netgraph socket .:%s -> %s:%s\n", ngc.ourhook, ngc.path, ngc.peerhook); if (NgSendMsg(dev->cs, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof ngc) < 0) { log_Printf(LogWARN, "Cannot connect PPPoE and socket netgraph " "nodes: %s\n", strerror(errno)); return ether_Abandon(dev, p); } /* Bring the Ethernet interface up */ path[ifacelen] = '\0'; /* Remove the trailing ':' */ if (!iface_SetFlags(path, IFF_UP)) log_Printf(LogWARN, "%s: Failed to set the IFF_UP flag on %s\n", p->link.name, path); /* And finally, request a connection to the given provider */ data = (struct ngpppoe_init_data *)alloca(sizeof *data + providerlen); snprintf(data->hook, sizeof data->hook, "%s", dev->hook); memcpy(data->data, provider, providerlen); data->data_len = providerlen; snprintf(connectpath, sizeof connectpath, ".:%s", dev->hook); log_Printf(LogDEBUG, "Sending PPPOE_CONNECT to %s\n", connectpath); if (NgSendMsg(dev->cs, connectpath, NGM_PPPOE_COOKIE, NGM_PPPOE_CONNECT, data, sizeof *data + providerlen) == -1) { log_Printf(LogWARN, "``%s'': Cannot start netgraph node: %s\n", connectpath, strerror(errno)); return ether_Abandon(dev, p); } /* Hook things up so that we monitor dev->cs */ p->desc.UpdateSet = ether_UpdateSet; p->desc.IsSet = ether_IsSet; p->desc.Read = ether_DescriptorRead; memcpy(&dev->dev, &baseetherdevice, sizeof dev->dev); switch (p->cfg.cd.necessity) { case CD_VARIABLE: dev->dev.cd.delay = p->cfg.cd.delay; break; case CD_REQUIRED: dev->dev.cd = p->cfg.cd; break; case CD_NOTREQUIRED: log_Printf(LogWARN, "%s: Carrier must be set, using ``set cd %d!''\n", p->link.name, dev->dev.cd.delay); case CD_DEFAULT: break; } dev->timeout = dev->dev.cd.delay; dev->connected = CARRIER_PENDING; /* This will be overridden by our session id - if provided by netgraph */ dev->slot = GetIfIndex(path); } else { /* See if we're a netgraph socket */ struct stat st; if (fstat(p->fd, &st) != -1 && S_ISSOCK(st.st_mode)) { struct sockaddr_storage ssock; struct sockaddr *sock = (struct sockaddr *)&ssock; int sz; sz = sizeof ssock; if (getsockname(p->fd, sock, &sz) == -1) { log_Printf(LogPHASE, "%s: Link is a closed socket !\n", p->link.name); close(p->fd); p->fd = -1; return NULL; } if (sock->sa_family == AF_NETGRAPH) { /* * It's a netgraph node... We can't determine hook names etc, so we * stay pretty impartial.... */ log_Printf(LogPHASE, "%s: Link is a netgraph node\n", p->link.name); if ((dev = malloc(sizeof *dev)) == NULL) { log_Printf(LogWARN, "%s: Cannot allocate an ether device: %s\n", p->link.name, strerror(errno)); return NULL; } memcpy(&dev->dev, &baseetherdevice, sizeof dev->dev); dev->cs = -1; dev->timeout = 0; dev->connected = CARRIER_OK; *dev->hook = '\0'; /* * If we're being envoked from pppoed(8), we may have a SESSIONID * set in the environment. If so, use it as the slot */ if ((sessionid = getenv("SESSIONID")) != NULL) { char *end; u_long slot; slot = strtoul(sessionid, &end, 16); dev->slot = end != sessionid && *end == '\0' ? slot : 0; } else dev->slot = 0; } } } if (dev) { physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); return &dev->dev; } return NULL; }
/* open the file and mmap it, necessary to go to READY state */ static gboolean gst_file_src_start (GstBaseSrc * basesrc) { GstFileSrc *src = GST_FILE_SRC (basesrc); struct stat stat_results; if (src->filename == NULL || src->filename[0] == '\0') goto no_filename; GST_INFO_OBJECT (src, "opening file %s", src->filename); /* open the file */ src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0); if (src->fd < 0) goto open_failed; /* check if it is a regular file, otherwise bail out */ if (fstat (src->fd, &stat_results) < 0) goto no_stat; if (S_ISDIR (stat_results.st_mode)) goto was_directory; if (S_ISSOCK (stat_results.st_mode)) goto was_socket; src->using_mmap = FALSE; src->read_position = 0; /* record if it's a regular (hence seekable and lengthable) file */ if (S_ISREG (stat_results.st_mode)) src->is_regular = TRUE; #ifdef HAVE_MMAP if (src->use_mmap) { /* FIXME: maybe we should only try to mmap if it's a regular file */ /* allocate the first mmap'd region if it's a regular file ? */ src->mapbuf = gst_file_src_map_region (src, 0, src->mapsize, TRUE); if (src->mapbuf != NULL) { GST_DEBUG_OBJECT (src, "using mmap for file"); src->using_mmap = TRUE; src->seekable = TRUE; } } if (src->mapbuf == NULL) #endif { /* If not in mmap mode, we need to check if the underlying file is * seekable. */ off_t res = lseek (src->fd, 0, SEEK_END); if (res < 0) { GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek " "failed: %s", g_strerror (errno)); src->seekable = FALSE; } else { src->seekable = TRUE; } lseek (src->fd, 0, SEEK_SET); } /* We can only really do seeking on regular files - for other file types, we * don't know their length, so seeking isn't useful/meaningful */ src->seekable = src->seekable && src->is_regular; return TRUE; /* ERROR */ no_filename: { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (_("No file name specified for reading.")), (NULL)); return FALSE; } open_failed: { switch (errno) { case ENOENT: GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), ("No such file \"%s\"", src->filename)); break; default: GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("Could not open file \"%s\" for reading."), src->filename), GST_ERROR_SYSTEM); break; } return FALSE; } no_stat: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("Could not get info on \"%s\"."), src->filename), (NULL)); close (src->fd); return FALSE; } was_directory: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("\"%s\" is a directory."), src->filename), (NULL)); close (src->fd); return FALSE; } was_socket: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (_("File \"%s\" is a socket."), src->filename), (NULL)); close (src->fd); return FALSE; } }
static int NativeMatchType( Tcl_Interp *interp, /* Interpreter to receive errors. */ CONST char *nativeEntry, /* Native path to check. */ CONST char *nativeName, /* Native filename to check. */ Tcl_GlobTypeData *types) /* Type description to match against. */ { Tcl_StatBuf buf; if (types == NULL) { /* * Simply check for the file's existence, but do it with lstat, in * case it is a link to a file which doesn't exist (since that case * would not show up if we used 'access' or 'stat') */ if (TclOSlstat(nativeEntry, &buf) != 0) { return 0; } } else { if (types->perm != 0) { if (TclOSstat(nativeEntry, &buf) != 0) { /* * Either the file has disappeared between the 'readdir' call * and the 'stat' call, or the file is a link to a file which * doesn't exist (which we could ascertain with lstat), or * there is some other strange problem. In all these cases, we * define this to mean the file does not match any defined * permission, and therefore it is not added to the list of * files to return. */ return 0; } /* * readonly means that there are NO write permissions (even for * user), but execute is OK for anybody OR that the user immutable * flag is set (where supported). */ if (((types->perm & TCL_GLOB_PERM_RONLY) && #if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) !(buf.st_flags & UF_IMMUTABLE) && #endif (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) || ((types->perm & TCL_GLOB_PERM_R) && (access(nativeEntry, R_OK) != 0)) || ((types->perm & TCL_GLOB_PERM_W) && (access(nativeEntry, W_OK) != 0)) || ((types->perm & TCL_GLOB_PERM_X) && (access(nativeEntry, X_OK) != 0)) #ifndef MAC_OSX_TCL || ((types->perm & TCL_GLOB_PERM_HIDDEN) && (*nativeName != '.')) #endif ) { return 0; } } if (types->type != 0) { if (types->perm == 0) { /* * We haven't yet done a stat on the file. */ if (TclOSstat(nativeEntry, &buf) != 0) { /* * Posix error occurred. The only ok case is if this is a * link to a nonexistent file, and the user did 'glob -l'. * So we check that here: */ if (types->type & TCL_GLOB_TYPE_LINK) { if (TclOSlstat(nativeEntry, &buf) == 0) { if (S_ISLNK(buf.st_mode)) { return 1; } } } return 0; } } /* * In order bcdpfls as in 'find -t' */ if (((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_DIR) && S_ISDIR(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))|| ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode)) #ifdef S_ISSOCK ||((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode)) #endif /* S_ISSOCK */ ) { /* * Do nothing - this file is ok. */ } else { #ifdef S_ISLNK if (types->type & TCL_GLOB_TYPE_LINK) { if (TclOSlstat(nativeEntry, &buf) == 0) { if (S_ISLNK(buf.st_mode)) { goto filetypeOK; } } } #endif /* S_ISLNK */ return 0; } } filetypeOK: ; #ifdef MAC_OSX_TCL if (types->macType != NULL || types->macCreator != NULL || (types->perm & TCL_GLOB_PERM_HIDDEN)) { int matchResult; if (types->perm == 0 && types->type == 0) { /* * We haven't yet done a stat on the file. */ if (TclOSstat(nativeEntry, &buf) != 0) { return 0; } } matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName, &buf, types); if (matchResult != 1) { return matchResult; } } #endif } return 1; }
static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub) { struct dirent **dirlist; int totalsize = 0, dircount, dirindex; char *path, *endpath; size_t len = strlen(name); /* Set up the path. */ /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */ path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1); if (!path) { perror(NULL); exit(8); } memcpy(path, name, len); endpath = path + len; *endpath = '/'; endpath++; /* read in the directory and sort */ dircount = scandir(name, &dirlist, 0, cramsort); if (dircount < 0) { perror(name); exit(8); } /* process directory */ for (dirindex = 0; dirindex < dircount; dirindex++) { struct dirent *dirent; struct entry *entry; struct stat st; int size; size_t namelen; dirent = dirlist[dirindex]; /* Ignore "." and ".." - we won't be adding them to the archive */ if (dirent->d_name[0] == '.') { if (dirent->d_name[1] == '\0') continue; if (dirent->d_name[1] == '.') { if (dirent->d_name[2] == '\0') continue; } } namelen = strlen(dirent->d_name); if (namelen > MAX_INPUT_NAMELEN) { fprintf(stderr, "Very long (%u bytes) filename `%s' found.\n" " Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile. Exiting.\n", namelen, dirent->d_name); exit(8); } memcpy(endpath, dirent->d_name, namelen + 1); if (lstat(path, &st) < 0) { perror(endpath); warn_skip = 1; continue; } entry = calloc(1, sizeof(struct entry)); if (!entry) { perror(NULL); exit(8); } entry->name = strdup(dirent->d_name); if (!entry->name) { perror(NULL); exit(8); } if (namelen > 255) { /* Can't happen when reading from ext2fs. */ /* TODO: we ought to avoid chopping in half multi-byte UTF8 characters. */ entry->name[namelen = 255] = '\0'; warn_namelen = 1; } entry->mode = st.st_mode; entry->size = st.st_size; entry->uid = st.st_uid; if (entry->uid >= 1 << CRAMFS_UID_WIDTH) warn_uid = 1; entry->gid = st.st_gid; if (entry->gid >= 1 << CRAMFS_GID_WIDTH) /* TODO: We ought to replace with a default gid instead of truncating; otherwise there are security problems. Maybe mode should be &= ~070. Same goes for uid once Linux supports >16-bit uids. */ warn_gid = 1; size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3); *fslen_ub += size; if (S_ISDIR(st.st_mode)) { entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub); } else if (S_ISREG(st.st_mode)) { /* TODO: We ought to open files in do_compress, one at a time, instead of amassing all these memory maps during parse_directory (which don't get used until do_compress anyway). As it is, we tend to get EMFILE errors (especially if mkcramfs is run by non-root). While we're at it, do analagously for symlinks (which would just save a little memory). */ int fd = open(path, O_RDONLY); if (fd < 0) { perror(path); warn_skip = 1; continue; } if (entry->size) { if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) { warn_size = 1; entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1; } entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0); if (-1 == (int) (long) entry->uncompressed) { perror("mmap"); exit(8); } } close(fd); } else if (S_ISLNK(st.st_mode)) { entry->uncompressed = malloc(entry->size); if (!entry->uncompressed) { perror(NULL); exit(8); } if (readlink(path, entry->uncompressed, entry->size) < 0) { perror(path); warn_skip = 1; continue; } } else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { /* maybe we should skip sockets */ entry->size = 0; } else { entry->size = st.st_rdev; if (entry->size & -(1<<CRAMFS_SIZE_WIDTH)) warn_dev = 1; } if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { int blocks = ((entry->size - 1) / blksize + 1); /* block pointers & data expansion allowance + data */ if(entry->size) *fslen_ub += (4+26)*blocks + entry->size + 3; } if (opt_xip && entry->mode & S_ISVTX) { /* worse case, depending on where the offsets falls, * a single XIP entry could expand the sizeof the * file system by 8k, since we're aligning the start * and end on page boundary. */ *fslen_ub += 2*PAGE_CACHE_SIZE; } /* Link it into the list */ *prev = entry; prev = &entry->next; totalsize += size; } free(path); free(dirlist); /* allocated by scandir() with malloc() */ return totalsize; }
static int getentropy_fallback(void *buf, size_t len) { uint8_t results[SHA512_DIGEST_LENGTH]; int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat; static int cnt; struct timespec ts; struct timeval tv; struct pst_vminfo pvi; struct pst_vm_status pvs; struct pst_dynamic pdy; struct rusage ru; sigset_t sigset; struct stat st; SHA512_CTX ctx; static pid_t lastpid; pid_t pid; size_t i, ii, m; char *p; pid = getpid(); if (lastpid == pid) { faster = 1; repeat = 2; } else { faster = 0; lastpid = pid; repeat = REPEAT; } for (i = 0; i < len; ) { int j; SHA512_Init(&ctx); for (j = 0; j < repeat; j++) { HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { cnt += (int)tv.tv_sec; cnt += (int)tv.tv_usec; } HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi); HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs); for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) HX(clock_gettime(cl[ii], &ts) == -1, ts); HX((pid = getpid()) == -1, pid); HX((pid = getsid(pid)) == -1, pid); HX((pid = getppid()) == -1, pid); HX((pid = getpgid(0)) == -1, pid); HX((e = getpriority(0, 0)) == -1, e); if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) { HD(errno); } else { HD(pdy.psd_avg_1_min); HD(pdy.psd_avg_5_min); HD(pdy.psd_avg_15_min); } if (!faster) { ts.tv_sec = 0; ts.tv_nsec = 1; (void) nanosleep(&ts, NULL); } HX(sigpending(&sigset) == -1, sigset); HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, sigset); HF(getentropy); /* an addr in this library */ HF(printf); /* an addr in libc */ p = (char *)&p; HD(p); /* an addr on stack */ p = (char *)&errno; HD(p); /* the addr of errno */ if (i == 0) { struct sockaddr_storage ss; struct statvfs stvfs; struct termios tios; socklen_t ssl; off_t off; /* * Prime-sized mappings encourage fragmentation; * thus exposing some address entropy. */ struct mm { size_t npg; void *p; } mm[] = { { 17, MAP_FAILED }, { 3, MAP_FAILED }, { 11, MAP_FAILED }, { 2, MAP_FAILED }, { 5, MAP_FAILED }, { 3, MAP_FAILED }, { 7, MAP_FAILED }, { 1, MAP_FAILED }, { 57, MAP_FAILED }, { 3, MAP_FAILED }, { 131, MAP_FAILED }, { 1, MAP_FAILED }, }; for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { HX(mm[m].p = mmap(NULL, mm[m].npg * pgs, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, (off_t)0), mm[m].p); if (mm[m].p != MAP_FAILED) { size_t mo; /* Touch some memory... */ p = mm[m].p; mo = cnt % (mm[m].npg * pgs - 1); p[mo] = 1; cnt += (int)((long)(mm[m].p) / pgs); } /* Check cnts and times... */ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) { HX((e = clock_gettime(cl[ii], &ts)) == -1, ts); if (e != -1) cnt += (int)ts.tv_nsec; } HX((e = getrusage(RUSAGE_SELF, &ru)) == -1, ru); if (e != -1) { cnt += (int)ru.ru_utime.tv_sec; cnt += (int)ru.ru_utime.tv_usec; } } for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { if (mm[m].p != MAP_FAILED) munmap(mm[m].p, mm[m].npg * pgs); mm[m].p = MAP_FAILED; } HX(stat(".", &st) == -1, st); HX(statvfs(".", &stvfs) == -1, stvfs); HX(stat("/", &st) == -1, st); HX(statvfs("/", &stvfs) == -1, stvfs); HX((e = fstat(0, &st)) == -1, st); if (e == -1) { if (S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { HX(fstatvfs(0, &stvfs) == -1, stvfs); HX((off = lseek(0, (off_t)0, SEEK_CUR)) < 0, off); } if (S_ISCHR(st.st_mode)) { HX(tcgetattr(0, &tios) == -1, tios); } else if (S_ISSOCK(st.st_mode)) { memset(&ss, 0, sizeof ss); ssl = sizeof(ss); HX(getpeername(0, (void *)&ss, &ssl) == -1, ss); } } HX((e = getrusage(RUSAGE_CHILDREN, &ru)) == -1, ru); if (e != -1) { cnt += (int)ru.ru_utime.tv_sec; cnt += (int)ru.ru_utime.tv_usec; } } else { /* Subsequent hashes absorb previous result */ HD(results); } HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { cnt += (int)tv.tv_sec; cnt += (int)tv.tv_usec; } HD(cnt); } SHA512_Final(results, &ctx); memcpy((char *)buf + i, results, min(sizeof(results), len - i)); i += min(sizeof(results), len - i); } explicit_bzero(&ctx, sizeof ctx); explicit_bzero(results, sizeof results); if (gotdata(buf, len) == 0) { errno = save_errno; return 0; /* satisfied */ } errno = EIO; return -1; }
int ino_to_fileinfo( struct inode *pino, char *databuf, UINT32 maxlen, PUINT32 plen, unsigned short level, unsigned short flags, unsigned short attrs, struct dirent *pDir, INT32 position, int TypeOp) { pCommonFileInfo pCommon; pFileName pFile; PINT32 pPosition; *plen = 0; /***************************************************************************/ /*** First field : long position if FF_GETPOS - nothing if FF_NOPOS ***/ /***************************************************************************/ if (TypeOp == TYPEOP_FILEFIND) { if (flags == FF_GETPOS) { if (sizeof(INT32) + *plen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for first field"); return ERROR_BUFFER_OVERFLOW; } pPosition = (PINT32) (databuf + *plen); *pPosition = position; *plen += sizeof(INT32); } } /***************************************************************************/ /***************************************************************************/ /*** Second field : common file information to all level/flags ***/ /***************************************************************************/ if (sizeof(CommonFileInfo) + *plen > maxlen) { kernel_printf("ino_to_fileinfo() - Buffer overflow for second field - len = %lu - maxlen = %lu", (UINT32) sizeof(CommonFileInfo) + (UINT32) (*plen), (UINT32) maxlen); return ERROR_BUFFER_OVERFLOW; } pCommon = (pCommonFileInfo) (databuf + *plen); date_unix2dos(pino->i_ctime, &(pCommon->timeCreate), &(pCommon->dateCreate)); date_unix2dos(pino->i_atime, &(pCommon->timeAccess), &(pCommon->dateAccess)); date_unix2dos(pino->i_mtime, &(pCommon->timeWrite), &(pCommon->dateWrite)); pCommon->cbEOF = pino->i_size; pCommon->cbAlloc = pino->i_blocks; pCommon->attr = FILE_NORMAL; if ((S_ISLNK(pino->i_mode)) || (S_ISBLK(pino->i_mode)) || (S_ISCHR(pino->i_mode)) || (S_ISFIFO(pino->i_mode)) || (S_ISSOCK(pino->i_mode))) { pCommon->attr |= FILE_SYSTEM; /*** UNIXish special files are seen as SYSTEM files ***/ } /* endif */ if (S_ISDIR(pino->i_mode)) { pCommon->attr |= FILE_DIRECTORY; } /* endif */ if ((!(pino->i_mode & S_IWUSR)) && (!(pino->i_mode & S_IWGRP)) && (!(pino->i_mode & S_IWOTH))) { pCommon->attr |= FILE_READONLY; } *plen += sizeof(CommonFileInfo); /***************************************************************************/ /***************************************************************************/ /*** Third field : nothing for level FIL_STANDARD ***/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /*** Third field : Size on disk of EA set for FIL_QUERYEASIZE ***/ /***************************************************************************/ if (level == FIL_QUERYEASIZE) { if (sizeof(INT32) + *plen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASIZE"); return ERROR_BUFFER_OVERFLOW; } *((PINT32) (databuf + *plen)) = 0; /*** No EAS in ext2 ***/ *plen += sizeof(INT32); } /***************************************************************************/ /***************************************************************************/ /*** Third field : FEAList for level QUERYEASFROMLIST ***/ /***************************************************************************/ if (level == FIL_QUERYEASFROMLIST) { if (sizeof(INT32) + *plen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASFROMLIST"); return ERROR_BUFFER_OVERFLOW; } *((PINT32) (databuf + *plen)) = 4; /*** No EAS in ext2 ***//* this is the length field of FEAList */ *plen += sizeof(INT32); } /***************************************************************************/ /***************************************************************************/ /*** Fourth field : name ***/ /***************************************************************************/ if (TypeOp == TYPEOP_FILEFIND) { if (*plen + sizeof(FileName) + pDir->d_reclen > maxlen) { fs_log("ino_to_fileinfo() - Buffer overflow for fourth field"); return ERROR_BUFFER_OVERFLOW; } pFile = (pFileName) (databuf + *plen); pFile->cbName = (unsigned char)pDir->d_reclen; /* name length WITHOUT '\0' */ strcpy(pFile->szName, pDir->d_name); /* name WITH '\0' */ *plen += sizeof(FileName) + pDir->d_reclen; /* sizeof(FileName) + strlen(Dir.d_name) */ } /***************************************************************************/ return NO_ERROR; }
static unsigned int walk_directory(struct imgspec* const spec, struct hostprog_path* const path, struct entry** previous) { struct dirent** dirlst; int dirlst_count; int dirlst_index; __u64 dir_sz = 0; __u64 dir_lvl = hostprog_path_lvls(path); dirlst_count = scandir(path->p_path, &dirlst, NULL, hostprog_scandirsort); if (dirlst_count < 0) error("failed to read \"%s\": %s", path->p_path, strerror(errno)); for (dirlst_index = 0; dirlst_index < dirlst_count; dirlst_index++) { struct dirent* dent = dirlst[dirlst_index]; /* Skip "." and ".." directories, just like mkcramfs. */ if (hostprog_path_dotdir(dent->d_name)) continue; hostprog_path_dirnamelvl(path, dir_lvl); if (hostprog_path_append(path, dent->d_name) != 0) error("failed to add a filename to the hostprog_path"); struct stat st; if (lstat(path->p_path, &st) < 0) { /* Maybe this should be an error? Files missing in the image * could possibly seem like an error to the user. */ warning("skipping \"unlstatable\" file \"%s\": %s", path->p_path, strerror(errno)); spec->sp_skipnodes++; continue; } if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { /* If the file is a regular file which can not be read, then * it might as well be skipped. * * This should also possibly be an error. */ if (access(path->p_path, R_OK) < 0) { warning("skipping unreadable file \"%s\": %s", path->p_path, strerror(errno)); spec->sp_skipnodes++; continue; } /* Completely empty files seems pretty pointless to include * in the image. */ if (!st.st_size) { message(VERBOSITY_1, ">>> skipping empty file \"%s\"", path->p_path); spec->sp_skipnodes++; continue; } } else if (!spec->sp_incsocks && S_ISSOCK(st.st_mode)) { warning("skipping socket \"%s\"", path->p_path); spec->sp_skipnodes++; continue; } /* Files should never be skipped after this point since that * would mess up the image size estimation. */ struct entry* ent = malloc(sizeof(*ent)); if (!ent) error("failed to alloc an entry for \"%s\"", path->p_path); memset(ent, 0, sizeof(*ent)); ent->e_name = strdup(dent->d_name); if (!ent->e_name) error("failed to copy the entry name for \"%s\"", path->p_path); ent->e_mode = st.st_mode; ent->e_size = st.st_size; ent->e_fd = -1; ENTRY_SET_XID(spec, ent, e_uid, st.st_uid, MICROFS_IUID_WIDTH); ENTRY_SET_XID(spec, ent, e_gid, st.st_gid, MICROFS_IGID_WIDTH); if (S_ISDIR(ent->e_mode)) { ent->e_size = walk_directory(spec, path, &ent->e_firstchild); } else if (S_ISREG(ent->e_mode) || S_ISLNK(ent->e_mode)) { if (ent->e_size > MICROFS_MAXFILESIZE) { error("\"%s\" is too big, max file size is %llu bytes", path->p_path, MICROFS_MAXFILESIZE); } else if (ent->e_size > MICROFS_MAXCRAMSIZE) { warning("\"%s\" is a big file, microfs works best with files" " smaller than %llu bytes", path->p_path, MICROFS_MAXCRAMSIZE); } ent->e_path = strdup(path->p_path); if (!ent->e_path) { error("failed to copy the entry path for \"%s\"", path->p_path); } if (spec->sp_shareblocks) { if (hostprog_stack_push(spec->sp_regstack, ent) < 0) error("failed to push an entry to the regular file stack: %s", strerror(errno)); } } else if (S_ISCHR(ent->e_mode) || S_ISBLK(ent->e_mode)) { ent->e_size = makedev_lim(major(st.st_rdev), minor(st.st_rdev), MICROFS_ISIZE_WIDTH); } else if (S_ISFIFO(ent->e_mode) || S_ISSOCK(ent->e_mode)) { ent->e_size = 0; } else { error("unexpected file mode encountered"); } /* %namelen() could actually fail here if the d_name is too * long, but that will terminate the program, so that is fine. */ dir_sz += update_upperbound(spec, ent, namelen(dent->d_name)); update_stats(spec, ent); message(VERBOSITY_1, "+ %c %s", nodtype(ent->e_mode), path->p_path); *previous = ent; previous = &ent->e_sibling; } free(dirlst); hostprog_path_dirnamelvl(path, dir_lvl); /* This should never happen, but if it ever does, it is * clearly an error. */ if (dir_sz > MICROFS_MAXDIRSIZE) { error("achievement unlocked: the directory size for \"%s\"" " is %llu bytes, the maximum supported size is %llu bytes" " - this is impressive in a very scary way", path->p_path, dir_sz, MICROFS_MAXDIRSIZE); } return dir_sz; }
char const * file_type (struct stat const *st) { /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107 for some of these formats. To keep diagnostics grammatical in English, the returned string must start with a consonant. */ /* Do these three first, as they're the most common. */ if (S_ISREG (st->st_mode)) return st->st_size == 0 ? _("regular empty file") : _("regular file"); if (S_ISDIR (st->st_mode)) return _("directory"); if (S_ISLNK (st->st_mode)) return _("symbolic link"); /* Do the S_TYPEIS* macros next, as they may be implemented in terms of S_ISNAM, and we want the more-specialized interpretation. */ if (S_TYPEISMQ (st)) return _("message queue"); if (S_TYPEISSEM (st)) return _("semaphore"); if (S_TYPEISSHM (st)) return _("shared memory object"); if (S_TYPEISTMO (st)) return _("typed memory object"); /* The remaining are in alphabetical order. */ if (S_ISBLK (st->st_mode)) return _("block special file"); if (S_ISCHR (st->st_mode)) return _("character special file"); if (S_ISCTG (st->st_mode)) return _("contiguous data"); if (S_ISFIFO (st->st_mode)) return _("fifo"); if (S_ISDOOR (st->st_mode)) return _("door"); if (S_ISMPB (st->st_mode)) return _("multiplexed block special file"); if (S_ISMPC (st->st_mode)) return _("multiplexed character special file"); if (S_ISMPX (st->st_mode)) return _("multiplexed file"); if (S_ISNAM (st->st_mode)) return _("named file"); if (S_ISNWK (st->st_mode)) return _("network special file"); if (S_ISOFD (st->st_mode)) return _("migrated file with data"); if (S_ISOFL (st->st_mode)) return _("migrated file without data"); if (S_ISPORT (st->st_mode)) return _("port"); if (S_ISSOCK (st->st_mode)) return _("socket"); if (S_ISWHT (st->st_mode)) return _("whiteout"); return _("weird file"); }
/* * Get a new inode. */ struct inode * ncp_iget(struct super_block *sb, struct ncp_entry_info *info) { struct inode *inode; if (info == NULL) { printk(KERN_ERR "ncp_iget: info is NULL\n"); return NULL; } inode = new_inode(sb); if (inode) { atomic_set(&NCP_FINFO(inode)->opened, info->opened); inode->i_mapping->backing_dev_info = sb->s_bdi; inode->i_ino = info->ino; ncp_set_attr(inode, info); if (S_ISREG(inode->i_mode)) { inode->i_op = &ncp_file_inode_operations; inode->i_fop = &ncp_file_operations; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ncp_dir_inode_operations; inode->i_fop = &ncp_dir_operations; #ifdef CONFIG_NCPFS_NFS_NS } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { init_special_inode(inode, inode->i_mode, new_decode_dev(info->i.nfs.rdev)); #endif #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &ncp_symlink_inode_operations; inode->i_data.a_ops = &ncp_symlink_aops; #endif } else { make_bad_inode(inode); } insert_inode_hash(inode); } else printk(KERN_ERR "ncp_iget: iget failed!\n"); return inode; }
void hpfs_read_inode(struct inode *i) { struct buffer_head *bh; struct fnode *fnode; struct super_block *sb = i->i_sb; struct hpfs_inode_info *hpfs_inode = hpfs_i(i); void *ea; int ea_size; if (!(fnode = hpfs_map_fnode(sb, i->i_ino, &bh))) { /*i->i_mode |= S_IFREG; i->i_mode &= ~0111; i->i_op = &hpfs_file_iops; i->i_fop = &hpfs_file_ops; clear_nlink(i);*/ make_bad_inode(i); return; } if (hpfs_sb(i->i_sb)->sb_eas) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) { if (ea_size == 2) { i_uid_write(i, le16_to_cpu(*(__le16*)ea)); hpfs_inode->i_ea_uid = 1; } kfree(ea); } if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) { if (ea_size == 2) { i_gid_write(i, le16_to_cpu(*(__le16*)ea)); hpfs_inode->i_ea_gid = 1; } kfree(ea); } if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) { kfree(ea); i->i_mode = S_IFLNK | 0777; i->i_op = &page_symlink_inode_operations; inode_nohighmem(i); i->i_data.a_ops = &hpfs_symlink_aops; set_nlink(i, 1); i->i_size = ea_size; i->i_blocks = 1; brelse(bh); return; } if ((ea = hpfs_get_ea(i->i_sb, fnode, "MODE", &ea_size))) { int rdev = 0; umode_t mode = hpfs_sb(sb)->sb_mode; if (ea_size == 2) { mode = le16_to_cpu(*(__le16*)ea); hpfs_inode->i_ea_mode = 1; } kfree(ea); i->i_mode = mode; if (S_ISBLK(mode) || S_ISCHR(mode)) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) { if (ea_size == 4) rdev = le32_to_cpu(*(__le32*)ea); kfree(ea); } } if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { brelse(bh); set_nlink(i, 1); i->i_size = 0; i->i_blocks = 1; init_special_inode(i, mode, new_decode_dev(rdev)); return; } } } if (fnode_is_dir(fnode)) { int n_dnodes, n_subdirs; i->i_mode |= S_IFDIR; i->i_op = &hpfs_dir_iops; i->i_fop = &hpfs_dir_ops; hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up); hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno); if (hpfs_sb(sb)->sb_chk >= 2) { struct buffer_head *bh0; if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0); } n_dnodes = 0; n_subdirs = 0; hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL); i->i_blocks = 4 * n_dnodes; i->i_size = 2048 * n_dnodes; set_nlink(i, 2 + n_subdirs); } else { i->i_mode |= S_IFREG; if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111; i->i_op = &hpfs_file_iops; i->i_fop = &hpfs_file_ops; set_nlink(i, 1); i->i_size = le32_to_cpu(fnode->file_size); i->i_blocks = ((i->i_size + 511) >> 9) + 1; i->i_data.a_ops = &hpfs_aops; hpfs_i(i)->mmu_private = i->i_size; } brelse(bh); }
static int copy_single_file(const char *from, const char *to) { FILE *from_stream, *to_stream; struct stat st; char buf[4096]; size_t len; if (check_the_same(from, to)) { fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); return RecursiveOp_Callback_Error; } if (lstat(from, &st)) { perror("lstat"); return RecursiveOp_Callback_Error; } if (S_ISLNK(st.st_mode)) { /* symbolic links should be copied in special way */ char *link_buffer; int need_free; ssize_t link_len; /* get large enough buffer to read link content */ if (st.st_size < sizeof(buf)) { link_buffer = buf; need_free = 0; } else { link_buffer = MEM_callocN(st.st_size + 2, "copy_single_file link_buffer"); need_free = 1; } link_len = readlink(from, link_buffer, st.st_size + 1); if (link_len < 0) { perror("readlink"); if (need_free) MEM_freeN(link_buffer); return RecursiveOp_Callback_Error; } link_buffer[link_len] = 0; if (symlink(link_buffer, to)) { perror("symlink"); if (need_free) MEM_freeN(link_buffer); return RecursiveOp_Callback_Error; } if (need_free) MEM_freeN(link_buffer); return RecursiveOp_Callback_OK; } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { /* copy special type of file */ if (mknod(to, st.st_mode, st.st_rdev)) { perror("mknod"); return RecursiveOp_Callback_Error; } if (set_permissions(to, &st)) return RecursiveOp_Callback_Error; return RecursiveOp_Callback_OK; } else if (!S_ISREG(st.st_mode)) { fprintf(stderr, "Copying of this kind of files isn't supported yet\n"); return RecursiveOp_Callback_Error; } from_stream = fopen(from, "rb"); if (!from_stream) { perror("fopen"); return RecursiveOp_Callback_Error; } to_stream = fopen(to, "wb"); if (!to_stream) { perror("fopen"); fclose(from_stream); return RecursiveOp_Callback_Error; } while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) { fwrite(buf, 1, len, to_stream); } fclose(to_stream); fclose(from_stream); if (set_permissions(to, &st)) return RecursiveOp_Callback_Error; return RecursiveOp_Callback_OK; }
static void analyze_file(const char *filename) { int fd, filekind; u8 filesize; struct stat sb; char *reason; SOURCE *s; print_line(0, "--- %s", filename); /* stat check */ if (stat(filename, &sb) < 0) { errore("Can't stat %.300s", filename); return; } filekind = 0; filesize = 0; reason = NULL; if (S_ISREG(sb.st_mode)) { filesize = sb.st_size; print_kind(filekind, filesize, 1); } else if (S_ISBLK(sb.st_mode)) filekind = 1; else if (S_ISCHR(sb.st_mode)) filekind = 2; else if (S_ISDIR(sb.st_mode)) reason = "Is a directory"; else if (S_ISFIFO(sb.st_mode)) reason = "Is a FIFO"; #ifdef S_ISSOCK else if (S_ISSOCK(sb.st_mode)) reason = "Is a socket"; #endif else reason = "Is an unknown kind of special file"; if (reason != NULL) { error("%.300s: %s", filename, reason); return; } /* Mac OS type & creator code (if running on Mac OS X) */ #ifdef USE_MACOS_TYPE if (filekind == 0) show_macos_type(filename); #endif /* empty regular files need no further analysis */ if (filekind == 0 && filesize == 0) return; /* open for reading */ fd = open(filename, O_RDONLY); if (fd < 0) { errore("Can't open %.300s", filename); return; } /* (try to) guard against TTY character devices */ if (filekind == 2) { if (isatty(fd)) { error("%.300s: Is a TTY device", filename); return; } } /* create a source */ s = init_file_source(fd, filekind); /* tell the user what it is */ if (filekind != 0) print_kind(filekind, s->size, s->size_known); /* now analyze it */ analyze_source(s, 0); /* finish it up */ close_source(s); }
int default_init() { struct stat s; int i; /* FIXME: other modules might need this, too */ rec_buffer_init(); send_buffer_init(); if (stat(drv.device, &s) == -1) { logprintf(LIRC_ERROR, "could not get file information for %s", drv.device); logperror(LIRC_ERROR, "default_init()"); return (0); } /* file could be unix socket, fifo and native lirc device */ if (S_ISSOCK(s.st_mode)) { struct sockaddr_un addr; addr.sun_family = AF_UNIX; strncpy(addr.sun_path, drv.device, sizeof(addr.sun_path) - 1); drv.fd = socket(AF_UNIX, SOCK_STREAM, 0); if (drv.fd == -1) { logprintf(LIRC_ERROR, "could not create socket"); logperror(LIRC_ERROR, "default_init()"); return (0); } if (connect(drv.fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { logprintf(LIRC_ERROR, "could not connect to unix socket %s", drv.device); logperror(LIRC_ERROR, "default_init()"); default_deinit(); close(drv.fd); return (0); } logprintf(LIRC_TRACE, "using unix socket lirc device"); drv.features = LIRC_CAN_REC_MODE2 | LIRC_CAN_SEND_PULSE; drv.rec_mode = LIRC_MODE_MODE2; /* this might change in future */ drv.send_mode = LIRC_MODE_PULSE; return (1); } if ((drv.fd = open(drv.device, O_RDWR)) < 0) { logprintf(LIRC_ERROR, "could not open %s", drv.device); logperror(LIRC_ERROR, "default_init()"); return (0); } if (S_ISFIFO(s.st_mode)) { logprintf(LIRC_TRACE, "using defaults for the Irman"); drv.features = LIRC_CAN_REC_MODE2; drv.rec_mode = LIRC_MODE_MODE2; /* this might change in future */ return (1); } else if (!S_ISCHR(s.st_mode)) { default_deinit(); logprintf(LIRC_ERROR, "%s is not a character device!!!", drv.device); logperror(LIRC_ERROR, "something went wrong during installation"); return (0); } else if (default_ioctl(LIRC_GET_FEATURES, &drv.features) == -1) { logprintf(LIRC_ERROR, "could not get hardware features"); logprintf(LIRC_ERROR, "this device driver does not support the LIRC ioctl interface"); if (major(s.st_rdev) == 13) { logprintf(LIRC_ERROR, "did you mean to use the devinput driver instead of the %s driver?", drv.name); } else { logprintf(LIRC_ERROR, "major number of %s is %lu", drv.device, (__u32) major(s.st_rdev)); logprintf(LIRC_ERROR, "make sure %s is a LIRC device and use a current version of the driver", drv.device); } default_deinit(); return (0); } else { if (!(LIRC_CAN_SEND(drv.features) || LIRC_CAN_REC(drv.features))) { logprintf(LIRC_TRACE, "driver supports neither sending nor receiving of IR signals"); } if (LIRC_CAN_SEND(drv.features) && LIRC_CAN_REC(drv.features)) { logprintf(LIRC_TRACE, "driver supports both sending and receiving"); } else if (LIRC_CAN_SEND(drv.features)) { logprintf(LIRC_TRACE, "driver supports sending"); } else if (LIRC_CAN_REC(drv.features)) { logprintf(LIRC_TRACE, "driver supports receiving"); } } /* set send/receive method */ drv.send_mode = 0; if (LIRC_CAN_SEND(drv.features)) { for (i = 0; supported_send_modes[i] != 0; i++) { if (LIRC_CAN_SEND(drv.features) == supported_send_modes[i]) { drv.send_mode = LIRC_SEND2MODE(supported_send_modes[i]); break; } } if (supported_send_modes[i] == 0) { logprintf(LIRC_NOTICE, "the send method of the driver is not yet supported by lircd"); } } drv.rec_mode = 0; if (LIRC_CAN_REC(drv.features)) { for (i = 0; supported_rec_modes[i] != 0; i++) { if (LIRC_CAN_REC(drv.features) == supported_rec_modes[i]) { drv.rec_mode = LIRC_REC2MODE(supported_rec_modes[i]); break; } } if (supported_rec_modes[i] == 0) { logprintf(LIRC_NOTICE, "the receive method of the driver is not yet supported by lircd"); } } if (drv.rec_mode == LIRC_MODE_MODE2) { /* get resolution */ drv.resolution = 0; if ((drv.features & LIRC_CAN_GET_REC_RESOLUTION) && (default_ioctl(LIRC_GET_REC_RESOLUTION, &drv.resolution) != -1)) { logprintf(LIRC_TRACE, "resolution of receiver: %d", drv.resolution); } } else if (drv.rec_mode == LIRC_MODE_LIRCCODE) { if (default_ioctl(LIRC_GET_LENGTH, (void*) &drv.code_length) == -1) { logprintf(LIRC_ERROR, "could not get code length"); logperror(LIRC_ERROR, "default_init()"); default_deinit(); return (0); } if (drv.code_length > sizeof(ir_code) * CHAR_BIT) { logprintf(LIRC_ERROR, "lircd can not handle %lu bit codes", drv.code_length); default_deinit(); return (0); } } if (!(drv.send_mode || drv.rec_mode)) { default_deinit(); return (0); } return (1); }
bool vfopen (char const *filename) { struct stat loadstat; struct stat savestat; char loadname [FILENAME_MAX]; char savename [FILENAME_MAX]; unsigned bailout = 0; unsigned version = 0; unsigned maximum = 0; char *extender; makepath (loadname, getenv ("PWD"), filename); makepath (savename, getenv ("PWD"), filename); if (lstat (loadname, &loadstat)) { error (bailout, errno, "Can't open %s", loadname); return (false); } if (S_ISDIR (loadstat.st_mode)) { error (bailout, 0, "Won't open %s: file is a folder", loadname); return (false); } if (S_ISLNK (loadstat.st_mode)) { error (bailout, 0, "Won't open %s: file is a symlink", loadname); return (false); } if (S_ISBLK (loadstat.st_mode)) { error (bailout, 0, "Won't open %s: file is a device", loadname); return (false); } if (S_ISCHR (loadstat.st_mode)) { error (bailout, 0, "Won't open %s: file is a device", loadname); return (false); } if (S_ISFIFO (loadstat.st_mode)) { error (bailout, 0, "Won't open %s: file is a fifo", loadname); return (false); } if (S_ISSOCK (loadstat.st_mode)) { error (bailout, 0, "Won't open %s: file is a socket", loadname); return (false); } for (version = FILE_VER_MAX; version > 0; version /= 10) { maximum++; } for (extender = savename; *extender; extender++); *extender++ = FILE_C_EXTENDER; for (version = 1; version < FILE_VER_MAX; version++) { unsigned value = version; unsigned digit = maximum; for (extender [digit] = (char) (0); digit-- > 0; value /= 10) { extender [digit] = (value % 10) + '0'; } if (lstat (savename, &savestat)) { if (!freopen (loadname, "rb", stdin)) { error (bailout, errno, "Can't open %s for input", loadname); return (false); } if (rename (loadname, savename)) { error (bailout, errno, "Can't rename %s as %s", loadname, savename); return (false); } if (!freopen (loadname, "wb", stdout)) { error (bailout, errno, "Can't open %s for output", loadname); return (false); } if (chmod (loadname, loadstat.st_mode)) { error (bailout, errno, "Can't preserve %s permissions", loadname); return (false); } if (chown (loadname, loadstat.st_uid, loadstat.st_gid)) { error (bailout, errno, "Can't preserve %s ownership", loadname); return (false); } return (true); } } error (bailout, 0, "Won't open %s: Too many file versions", loadname); return (false); }
struct super_block * ncp_read_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data; struct ncp_server *server; struct file *ncp_filp; struct inode *root_inode; kdev_t dev = sb->s_dev; int error; #ifdef CONFIG_NCPFS_PACKET_SIGNING int options; #endif struct ncpfs_inode_info finfo; MOD_INC_USE_COUNT; if (data == NULL) goto out_no_data; if (data->version != NCP_MOUNT_VERSION) goto out_bad_mount; ncp_filp = fget(data->ncp_fd); if (!ncp_filp) goto out_bad_file; if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode)) goto out_bad_file2; lock_super(sb); sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_dev = dev; sb->s_op = &ncp_sops; /* We must malloc our own super-block info */ server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server), GFP_KERNEL); if (server == NULL) goto out_no_server; NCP_SBP(sb) = server; server->ncp_filp = ncp_filp; server->lock = 0; server->wait = NULL; server->packet = NULL; server->buffer_size = 0; server->conn_status = 0; server->root_dentry = NULL; server->root_setuped = 0; #ifdef CONFIG_NCPFS_PACKET_SIGNING server->sign_wanted = 0; server->sign_active = 0; #endif server->auth.auth_type = NCP_AUTH_NONE; server->auth.object_name_len = 0; server->auth.object_name = NULL; server->auth.object_type = 0; server->priv.len = 0; server->priv.data = NULL; server->m = *data; /* Althought anything producing this is buggy, it happens now because of PATH_MAX changes.. */ if (server->m.time_out < 10) { server->m.time_out = 10; printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); } server->m.file_mode = (server->m.file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG; server->m.dir_mode = (server->m.dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR; server->packet_size = NCP_PACKET_SIZE; server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL); if (server->packet == NULL) goto out_no_packet; ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); if (error < 0) goto out_no_connect; DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); #ifdef CONFIG_NCPFS_PACKET_SIGNING if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE, NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0) { if (options != NCP_DEFAULT_OPTIONS) { if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE, options & 2, &(server->buffer_size), &options) != 0) { goto out_no_bufsize; } } if (options & 2) server->sign_wanted = 1; } else #endif /* CONFIG_NCPFS_PACKET_SIGNING */ if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE, &(server->buffer_size)) != 0) goto out_no_bufsize; DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size); ncp_init_root(server, &finfo); server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS; root_inode = ncp_iget(sb, &finfo); if (!root_inode) goto out_no_root; DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL); if (!sb->s_root) goto out_no_root; server->root_dentry->d_op = &ncp_dentry_operations; unlock_super(sb); return sb; out_no_root: printk(KERN_ERR "ncp_read_super: get root inode failed\n"); iput(root_inode); goto out_disconnect; out_no_bufsize: printk(KERN_ERR "ncp_read_super: could not get bufsize\n"); out_disconnect: ncp_lock_server(server); ncp_disconnect(server); ncp_unlock_server(server); goto out_free_packet; out_no_connect: printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error); out_free_packet: ncp_kfree_s(server->packet, server->packet_size); goto out_free_server; out_no_packet: printk(KERN_ERR "ncp_read_super: could not alloc packet\n"); out_free_server: ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); goto out_unlock; out_no_server: printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n"); out_unlock: /* 23/12/1998 Marcin Dalecki <*****@*****.**>: * * The previously used put_filp(ncp_filp); was bogous, since * it doesn't proper unlocking. */ fput(ncp_filp); unlock_super(sb); goto out; out_bad_file2: fput(ncp_filp); out_bad_file: printk(KERN_ERR "ncp_read_super: invalid ncp socket\n"); goto out; out_bad_mount: printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n", NCP_MOUNT_VERSION); goto out; out_no_data: printk(KERN_ERR "ncp_read_super: missing data argument\n"); out: sb->s_dev = 0; MOD_DEC_USE_COUNT; return NULL; }
bool Entry::is_socket() { return S_ISSOCK(archive_entry_filetype(_entry)); }
isc_result_t isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { int fd; struct stat _stat; isc_boolean_t is_usocket = ISC_FALSE; isc_boolean_t is_connected = ISC_FALSE; isc_result_t ret; isc_entropysource_t *source; REQUIRE(VALID_ENTROPY(ent)); REQUIRE(fname != NULL); LOCK(&ent->lock); if (stat(fname, &_stat) < 0) { ret = isc__errno2result(errno); goto errout; } /* * Solaris 2.5.1 does not have support for sockets (S_IFSOCK), * but it does return type S_IFIFO (the OS believes that * the socket is a fifo). This may be an issue if we tell * the program to look at an actual FIFO as its source of * entropy. */ #if defined(S_ISSOCK) if (S_ISSOCK(_stat.st_mode)) is_usocket = ISC_TRUE; #endif #if defined(S_ISFIFO) && defined(sun) if (S_ISFIFO(_stat.st_mode)) is_usocket = ISC_TRUE; #endif if (is_usocket) fd = socket(PF_UNIX, SOCK_STREAM, 0); else fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0); if (fd < 0) { ret = isc__errno2result(errno); goto errout; } ret = make_nonblock(fd); if (ret != ISC_R_SUCCESS) goto closefd; if (is_usocket) { struct sockaddr_un sname; memset(&sname, 0, sizeof(sname)); sname.sun_family = AF_UNIX; strlcpy(sname.sun_path, fname, sizeof(sname.sun_path)); #ifdef ISC_PLATFORM_HAVESALEN #if !defined(SUN_LEN) #define SUN_LEN(su) \ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) #endif sname.sun_len = SUN_LEN(&sname); #endif if (connect(fd, (struct sockaddr *) &sname, sizeof(struct sockaddr_un)) < 0) { if (errno != EINPROGRESS) { ret = isc__errno2result(errno); goto closefd; } } else is_connected = ISC_TRUE; } source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); if (source == NULL) { ret = ISC_R_NOMEMORY; goto closefd; } /* * From here down, no failures can occur. */ source->magic = SOURCE_MAGIC; source->ent = ent; source->total = 0; source->bad = ISC_FALSE; memset(source->name, 0, sizeof(source->name)); ISC_LINK_INIT(source, link); if (is_usocket) { source->sources.usocket.handle = fd; if (is_connected) source->sources.usocket.status = isc_usocketsource_connected; else source->sources.usocket.status = isc_usocketsource_connecting; source->sources.usocket.sz_to_recv = 0; source->type = ENTROPY_SOURCETYPE_USOCKET; } else { source->sources.file.handle = fd; source->type = ENTROPY_SOURCETYPE_FILE; } /* * Hook it into the entropy system. */ ISC_LIST_APPEND(ent->sources, source, link); ent->nsources++; UNLOCK(&ent->lock); return (ISC_R_SUCCESS); closefd: (void)close(fd); errout: UNLOCK(&ent->lock); return (ret); }
void getDirFileInfo(char dirname[]) { DIR *dir; struct dirent *dirent; int i = 0; struct stat *buf; struct passwd *usr; struct group *grp; char filename[80] = {0}; buf = (struct stat *)malloc(sizeof(struct stat)); if((dir = opendir(dirname)) == NULL) { my_err("opendir", __LINE__); } while((dirent = readdir(dir)) != NULL) { strcpy(filename, dirname); strcat(filename, "/"); strcat(filename, dirent->d_name); lstat(filename, buf); //用lstat避免奇奇怪怪的错误 //获取文件类型 if(S_ISLNK(buf->st_mode)) { fileinfo[i].type = 'l'; } else if(S_ISREG(buf->st_mode)) { fileinfo[i].type = '-'; } else if(S_ISDIR(buf->st_mode)) { fileinfo[i].type = 'd'; } else if(S_ISCHR(buf->st_mode)) { fileinfo[i].type = 'c'; } else if(S_ISBLK(buf->st_mode)) { fileinfo[i].type = 'b'; } else if(S_ISFIFO(buf->st_mode)) { fileinfo[i].type = 'f'; } else if(S_ISSOCK(buf->st_mode)) { fileinfo[i].type = 's'; } //获取文件权限 fileinfo[i].mode[0] = (buf->st_mode & S_IRUSR) ? 'r' : '-'; fileinfo[i].mode[1] = (buf->st_mode & S_IWUSR) ? 'w' : '-'; fileinfo[i].mode[2] = (buf->st_mode & S_IXUSR) ? 'x' : '-'; fileinfo[i].mode[3] = (buf->st_mode & S_IRGRP) ? 'r' : '-'; fileinfo[i].mode[4] = (buf->st_mode & S_IWGRP) ? 'w' : '-'; fileinfo[i].mode[5] = (buf->st_mode & S_IXGRP) ? 'x' : '-'; fileinfo[i].mode[6] = (buf->st_mode & S_IROTH) ? 'r' : '-'; fileinfo[i].mode[7] = (buf->st_mode & S_IWOTH) ? 'w' : '-'; fileinfo[i].mode[8] = (buf->st_mode & S_IXOTH) ? 'x' : '-'; printf("%s\n", fileinfo[i].mode); //获取文件硬链接的个数 fileinfo[i].number = buf->st_nlink; //获取文件的所有者 usr = getpwuid(buf->st_uid); strcpy(fileinfo[i].uid, usr->pw_name); //获取文件所有者的所属组 grp = getgrgid(buf->st_gid); strcpy(fileinfo[i].gid, grp->gr_name); //获取文件的大小 fileinfo[i].size = buf->st_size; //获取文件最后更改的时间 fileinfo[i].mtime = buf->st_mtime; //获取文件的文件名 strcpy(fileinfo[i].filename, dirent->d_name); i++; } }