void mode_to_letters(int mode, char * str) { strcpy(str, "----------"); /* default=无参数 */ if (S_ISDIR(mode)) str[0] = 'd'; /* 目录 */ if (S_ISCHR(mode)) str[0] = 'c'; /* 字符设备 */ if (S_ISBLK(mode)) str[0] = 'b'; /* 块设备 */ if (mode & S_IRUSR) //按位与,看mode是否有S_IRUSR权限 str[1] = 'r'; /* 用户权限 */ if (mode & S_IWUSR) str[2] = 'w'; if (mode & S_IXUSR) str[3] = 'x'; if (mode & S_IRGRP) str[4] = 'r'; /* 组权限 */ if (mode & S_IWGRP) str[5] = 'w'; if (mode & S_IXGRP) str[6] = 'x'; if (mode & S_IROTH) str[7] = 'r'; /* 其人的权限 */ if (mode & S_IWOTH) str[8] = 'w'; if (mode & S_IXOTH) str[9] = 'x'; }
/* * Display information about the current file. * * The format here roughly duplicates the output of 'ls -l'. * This is based on SUSv2, where 'tar tv' is documented as * listing additional information in an "unspecified format," * and 'pax -l' is documented as using the same format as 'ls -l'. */ static void list_item_verbose(struct cpio *cpio, struct archive_entry *entry) { char size[32]; char date[32]; char uids[16], gids[16]; const char *uname, *gname; FILE *out = stdout; const struct stat *st; const char *fmt; time_t tim; static time_t now; st = archive_entry_stat(entry); if (!now) time(&now); if (cpio->option_numeric_uid_gid) { /* Format numeric uid/gid for display. */ snprintf(uids, sizeof(uids), "%d", (int)archive_entry_uid(entry)); uname = uids; snprintf(gids, sizeof(gids), "%d", (int)archive_entry_gid(entry)); gname = gids; } else { /* Use uname if it's present, else lookup name from uid. */ uname = archive_entry_uname(entry); if (uname == NULL) uname = lookup_uname(cpio, archive_entry_uid(entry)); /* Use gname if it's present, else lookup name from gid. */ gname = archive_entry_gname(entry); if (gname == NULL) gname = lookup_gname(cpio, archive_entry_gid(entry)); } /* Print device number or file size. */ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { snprintf(size, sizeof(size), "%lu,%lu", (unsigned long)major(st->st_rdev), (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */ } else { snprintf(size, sizeof(size), CPIO_FILESIZE_PRINTF, (CPIO_FILESIZE_TYPE)st->st_size); } /* Format the time using 'ls -l' conventions. */ tim = (time_t)st->st_mtime; #if defined(_WIN32) && !defined(__CYGWIN__) /* Windows' strftime function does not support %e format. */ if (abs(tim - now) > (365/2)*86400) fmt = cpio->day_first ? "%d %b %Y" : "%b %d %Y"; else fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M"; #else if (abs(tim - now) > (365/2)*86400) fmt = cpio->day_first ? "%e %b %Y" : "%b %e %Y"; else fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M"; #endif strftime(date, sizeof(date), fmt, localtime(&tim)); fprintf(out, "%s%3d %-8s %-8s %8s %12s %s", archive_entry_strmode(entry), archive_entry_nlink(entry), uname, gname, size, date, archive_entry_pathname(entry)); /* Extra information for links. */ if (archive_entry_hardlink(entry)) /* Hard link */ fprintf(out, " link to %s", archive_entry_hardlink(entry)); else if (archive_entry_symlink(entry)) /* Symbolic link */ fprintf(out, " -> %s", archive_entry_symlink(entry)); fprintf(out, "\n"); }
/* * sys_sync_file_range() permits finely controlled syncing over a segment of * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is * zero then sys_sync_file_range() will operate from offset out to EOF. * * The flag bits are: * * SYNC_FILE_RANGE_WAIT_BEFORE: wait upon writeout of all pages in the range * before performing the write. * * SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the * range which are not presently under writeback. Note that this may block for * significant periods due to exhaustion of disk request structures. * * SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range * after performing the write. * * Useful combinations of the flag bits are: * * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE: ensures that all pages * in the range which were dirty on entry to sys_sync_file_range() are placed * under writeout. This is a start-write-for-data-integrity operation. * * SYNC_FILE_RANGE_WRITE: start writeout of all dirty pages in the range which * are not presently under writeout. This is an asynchronous flush-to-disk * operation. Not suitable for data integrity operations. * * SYNC_FILE_RANGE_WAIT_BEFORE (or SYNC_FILE_RANGE_WAIT_AFTER): wait for * completion of writeout of all pages in the range. This will be used after an * earlier SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE operation to wait * for that operation to complete and to return the result. * * SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER: * a traditional sync() operation. This is a write-for-data-integrity operation * which will ensure that all pages in the range which were dirty on entry to * sys_sync_file_range() are committed to disk. * * * SYNC_FILE_RANGE_WAIT_BEFORE and SYNC_FILE_RANGE_WAIT_AFTER will detect any * I/O errors or ENOSPC conditions and will return those to the caller, after * clearing the EIO and ENOSPC flags in the address_space. * * It should be noted that none of these operations write out the file's * metadata. So unless the application is strictly performing overwrites of * already-instantiated disk blocks, there are no guarantees here that the data * will be available after a crash. */ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, unsigned int flags) { #ifdef CONFIG_DYNAMIC_FSYNC if (likely(dyn_fsync_active && !power_suspend_active)) return 0; else { #endif int ret; struct file *file; struct address_space *mapping; loff_t endbyte; /* inclusive */ int fput_needed; umode_t i_mode; if (!fsync_enabled) return 0; ret = -EINVAL; if (flags & ~VALID_FLAGS) goto out; endbyte = offset + nbytes; if ((s64)offset < 0) goto out; if ((s64)endbyte < 0) goto out; if (endbyte < offset) goto out; if (sizeof(pgoff_t) == 4) { if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) { /* * The range starts outside a 32 bit machine's * pagecache addressing capabilities. Let it "succeed" */ ret = 0; goto out; } if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) { /* * Out to EOF */ nbytes = 0; } } if (nbytes == 0) endbyte = LLONG_MAX; else endbyte--; /* inclusive */ ret = -EBADF; file = fget_light(fd, &fput_needed); if (!file) goto out; i_mode = file->f_path.dentry->d_inode->i_mode; ret = -ESPIPE; if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) && !S_ISLNK(i_mode)) goto out_put; mapping = file->f_mapping; if (!mapping) { ret = -EINVAL; goto out_put; } ret = 0; if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) { ret = filemap_fdatawait_range(mapping, offset, endbyte); if (ret < 0) goto out_put; } if (flags & SYNC_FILE_RANGE_WRITE) { ret = filemap_fdatawrite_range(mapping, offset, endbyte); if (ret < 0) goto out_put; } if (flags & SYNC_FILE_RANGE_WAIT_AFTER) ret = filemap_fdatawait_range(mapping, offset, endbyte); out_put: fput_light(file, fput_needed); out: return ret; #ifdef CONFIG_DYNAMIC_FSYNC } #endif }
static int ocfs2_read_locked_inode(struct inode *inode, struct ocfs2_find_inode_args *args) { struct super_block *sb; struct ocfs2_super *osb; struct ocfs2_dinode *fe; struct buffer_head *bh = NULL; int status, can_lock; u32 generation = 0; status = -EINVAL; sb = inode->i_sb; osb = OCFS2_SB(sb); /* * To improve performance of cold-cache inode stats, we take * the cluster lock here if possible. * * Generally, OCFS2 never trusts the contents of an inode * unless it's holding a cluster lock, so taking it here isn't * a correctness issue as much as it is a performance * improvement. * * There are three times when taking the lock is not a good idea: * * 1) During startup, before we have initialized the DLM. * * 2) If we are reading certain system files which never get * cluster locks (local alloc, truncate log). * * 3) If the process doing the iget() is responsible for * orphan dir recovery. We're holding the orphan dir lock and * can get into a deadlock with another process on another * node in ->delete_inode(). * * #1 and #2 can be simply solved by never taking the lock * here for system files (which are the only type we read * during mount). It's a heavier approach, but our main * concern is user-accessible files anyway. * * #3 works itself out because we'll eventually take the * cluster lock before trusting anything anyway. */ can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE) && !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) && !ocfs2_mount_local(osb); trace_ocfs2_read_locked_inode( (unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock); /* * To maintain backwards compatibility with older versions of * ocfs2-tools, we still store the generation value for system * files. The only ones that actually matter to userspace are * the journals, but it's easier and inexpensive to just flag * all system files similarly. */ if (args->fi_flags & OCFS2_FI_FLAG_SYSFILE) generation = osb->fs_generation; ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres, OCFS2_LOCK_TYPE_META, generation, inode); ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres, OCFS2_LOCK_TYPE_OPEN, 0, inode); if (can_lock) { status = ocfs2_open_lock(inode); if (status) { make_bad_inode(inode); mlog_errno(status); return status; } status = ocfs2_inode_lock(inode, NULL, 0); if (status) { make_bad_inode(inode); mlog_errno(status); return status; } } if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) { status = ocfs2_try_open_lock(inode, 0); if (status) { make_bad_inode(inode); return status; } } if (can_lock) { status = ocfs2_read_inode_block_full(inode, &bh, OCFS2_BH_IGNORE_CACHE); } else { status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh); /* * If buffer is in jbd, then its checksum may not have been * computed as yet. */ if (!status && !buffer_jbd(bh)) status = ocfs2_validate_inode_block(osb->sb, bh); } if (status < 0) { mlog_errno(status); goto bail; } status = -EINVAL; fe = (struct ocfs2_dinode *) bh->b_data; /* * This is a code bug. Right now the caller needs to * understand whether it is asking for a system file inode or * not so the proper lock names can be built. */ mlog_bug_on_msg(!!(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) != !!(args->fi_flags & OCFS2_FI_FLAG_SYSFILE), "Inode %llu: system file state is ambigous\n", (unsigned long long)args->fi_blkno); if (S_ISCHR(le16_to_cpu(fe->i_mode)) || S_ISBLK(le16_to_cpu(fe->i_mode))) inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); ocfs2_populate_inode(inode, fe, 0); BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno)); status = 0; bail: if (can_lock) ocfs2_inode_unlock(inode, 0); if (status < 0) make_bad_inode(inode); brelse(bh); return status; }
static int ex_dir_list2html_process(Vstr_base *s1, Vstr_base *s2, int *parsed_header, int *row_num) { size_t pos = 0; size_t len = 0; size_t ns1 = vstr_parse_netstr(s2, 1, s2->len, &pos, &len); Vstr_sect_node name[1] = {{0,0}}; Vstr_sect_node size[1] = {{0,0}}; Vstr_sect_node type[1] = {{0,0}}; Vstr_sect_node mtim[1] = {{0,0}}; Vstr_sect_node perm[1] = {{0,0}}; if (!ns1) { if ((len > EX_MAX_R_DATA_INCORE) || (s2->len > EX_MAX_R_DATA_INCORE)) errx(EXIT_FAILURE, "bad input"); return (FALSE); } if (!*parsed_header) { size_t vpos = 0; size_t vlen = 0; size_t nst = 0; if (!(nst = vstr_parse_netstr(s2, pos, len, &vpos, &vlen))) errx(EXIT_FAILURE, "bad input"); pos += nst; len -= nst; if (!vstr_cmp_cstr_eq(s2, vpos, vlen, "version")) errx(EXIT_FAILURE, "bad input"); if (!(nst = vstr_parse_netstr(s2, pos, len, &vpos, &vlen))) errx(EXIT_FAILURE, "bad input"); pos += nst; len -= nst; if (!vstr_cmp_cstr_eq(s2, vpos, vlen, "2")) errx(EXIT_FAILURE, "Unsupported version"); *parsed_header = TRUE; len = 0; } while (len) { size_t kpos = 0; size_t klen = 0; size_t vpos = 0; size_t vlen = 0; size_t nst = 0; if (!(nst = vstr_parse_netstr(s2, pos, len, &kpos, &klen))) errx(EXIT_FAILURE, "bad input"); pos += nst; len -= nst; if (!(nst = vstr_parse_netstr(s2, pos, len, &vpos, &vlen))) errx(EXIT_FAILURE, "bad input"); pos += nst; len -= nst; if (0) { } else if (vstr_cmp_cstr_eq(s2, kpos, klen, "name")) { name->pos = vpos; name->len = vlen; } else if (vstr_cmp_cstr_eq(s2, kpos, klen, "type")) { type->pos = vpos; type->len = vlen; } else if (vstr_cmp_cstr_eq(s2, kpos, klen, "perms")) { perm->pos = vpos; perm->len = vlen; } else if (vstr_cmp_cstr_eq(s2, kpos, klen, "size")) { size->pos = vpos; size->len = vlen; } else if (vstr_cmp_cstr_eq(s2, kpos, klen, "mtime")) { mtim->pos = vpos; mtim->len = vlen; } } if (name->pos) { Vstr_base *href = vstr_dup_vstr(NULL, s2, name->pos, name->len, 0); Vstr_base *text = vstr_dup_vstr(NULL, s2, name->pos, name->len, 0); VSTR_AUTOCONF_uintmax_t type_val = 0; VSTR_AUTOCONF_uintmax_t val = 0; time_t tval = 0; *row_num %= 2; ++*row_num; if (!href || !vstr_conv_encode_uri(href, 1, href->len)) errno = ENOMEM, err(EXIT_FAILURE, "html"); if (!text || !html_conv_encode_data(text, 1, text->len)) errno = ENOMEM, err(EXIT_FAILURE, "html"); if (type->pos) type_val = vstr_parse_uintmax(s2, type->pos, type->len, 8, NULL, NULL); vstr_add_fmt(s1, s1->len, " <tr class=\"r%d\"> <td class=\"cn\">", *row_num); if (type_val && S_ISDIR(type_val)) vstr_add_fmt(s1, s1->len, "<a class=\"%s\" " "href=\"%s${vstr:%p%zu%zu%u}%s\">${vstr:%p%zu%zu%u}</a>", "dir", def_prefix, href, (size_t)1, href->len, 0, "/", text, (size_t)1, text->len, 0); else if (type_val && S_ISLNK(type_val)) vstr_add_fmt(s1, s1->len, "<a class=\"%s\" " "href=\"%s${vstr:%p%zu%zu%u}%s\">${vstr:%p%zu%zu%u}</a>", "link", def_prefix, href, (size_t)1, href->len, 0, "", text, (size_t)1, text->len, 0); else vstr_add_fmt(s1, s1->len, "<a class=\"%s\" " "href=\"%s${vstr:%p%zu%zu%u}%s\">${vstr:%p%zu%zu%u}</a>", "file", def_prefix, href, (size_t)1, href->len, 0, "", text, (size_t)1, text->len, 0); vstr_add_fmt(s1, s1->len, "</td>"); vstr_free_base(href); href = NULL; vstr_free_base(text); text = NULL; if (!size->pos) vstr_add_cstr_buf(s1, s1->len, " <td class=\"csz\"></td>"); else { val = vstr_parse_uintmax(s2, size->pos, size->len, 10, NULL, NULL); vstr_add_fmt(s1, s1->len, " <td class=\"csz\">${BKMG.ju:%ju}</td>", val); } if (output_mtime && !mtim->pos) vstr_add_cstr_buf(s1, s1->len, " <td class=\"cmt\"></td>"); else if (output_mtime) { struct tm *tm_val = NULL; tval = vstr_parse_uintmax(s2, mtim->pos, mtim->len, 10, NULL, NULL); if (!(tm_val = localtime(&tval))) vstr_add_cstr_buf(s1, s1->len, " <td class=\"cmt\">unknown</td>"); else { char buf[4096]; strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm_val); vstr_add_fmt(s1, s1->len, " <td class=\"cmt\">%s</td>", buf); } } if (output_perms && !perm->pos) vstr_add_cstr_buf(s1, s1->len, " <td class=\"cp\"></td>"); else if (output_perms) { val = vstr_parse_uintmax(s2, perm->pos, perm->len, 8, NULL, NULL); switch (val & 07) { case 07: if (type_val && S_ISDIR(type_val)) vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Read, write and search", "rwx"); else vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Read, write and execute", "rwx"); break; case 06: vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Read and write", "rw-"); break; case 05: if (type_val && S_ISDIR(type_val)) vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Read and search", "r-x"); else vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Read and execute", "r-x"); break; case 04: vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Read only", "r--"); break; case 03: if (type_val && S_ISDIR(type_val)) vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Write and search", "-wx"); else vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Write and execute", "-wx"); break; case 02: vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Write only", "-w-"); break; case 01: if (type_val && S_ISDIR(type_val)) vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Search only", "--x"); else vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "Execute only", "--x"); break; case 0: vstr_add_fmt(s1, s1->len, " <td class=\"cp\" title=\"%s\">%s</td>", "None", "---"); break; } } if (!type_val) vstr_add_cstr_buf(s1, s1->len, " <td class=\"ct\"></td>"); else { vstr_add_cstr_buf(s1, s1->len, " <td class=\"ct\">"); if (0) { } else if (S_ISREG(type_val)) { /* do nothing */ } else if (S_ISDIR(type_val)) vstr_add_cstr_buf(s1, s1->len, "(directory)"); else if (S_ISCHR(type_val)) vstr_add_cstr_buf(s1, s1->len, "(character device)"); else if (S_ISBLK(type_val)) vstr_add_cstr_buf(s1, s1->len, "(block device)"); else if (S_ISLNK(type_val)) vstr_add_cstr_buf(s1, s1->len, "(symbolic link)"); else if (S_ISSOCK(type_val)) vstr_add_cstr_buf(s1, s1->len, "(socket)"); else vstr_add_cstr_buf(s1, s1->len, "(UNKNOWN)"); vstr_add_cstr_buf(s1, s1->len, "</td>"); } vstr_add_cstr_buf(s1, s1->len, "</tr>\n"); } vstr_del(s2, 1, ns1); return (TRUE); }
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; } return 1; } 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 /* MAC_OSX_TCL */ ) { 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) && (TclOSlstat(nativeEntry, &buf) == 0) && S_ISLNK(buf.st_mode)) { return 1; } return 0; } } /* * In order bcdpsfl 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))|| #ifdef S_ISSOCK ((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))|| #endif /* S_ISSOCK */ ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))) { /* * Do nothing - this file is ok. */ } else { #ifdef S_ISLNK if ((types->type & TCL_GLOB_TYPE_LINK) && (TclOSlstat(nativeEntry, &buf) == 0) && S_ISLNK(buf.st_mode)) { goto filetypeOK; } #endif /* S_ISLNK */ return 0; } } filetypeOK: /* * If we're on OSX, we also have to worry about matching the file creator * code (if specified). Do that now. */ #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 /* MAC_OSX_TCL */ return 1; }
/* Returns whether any color sequence was printed. */ bool _rl_print_color_indicator (const char *f) { enum indicator_no colored_filetype; COLOR_EXT_TYPE *ext; /* Color extension */ size_t len; /* Length of name */ const char* name; char *filename; struct stat astat, linkstat; mode_t mode; int linkok; /* 1 == ok, 0 == dangling symlink, -1 == missing */ int stat_ok; name = f; /* This should already have undergone tilde expansion */ filename = 0; if (rl_filename_stat_hook) { filename = savestring (f); (*rl_filename_stat_hook) (&filename); name = filename; } #if defined (HAVE_LSTAT) stat_ok = lstat(name, &astat); #else stat_ok = stat(name, &astat); #endif if (stat_ok == 0) { mode = astat.st_mode; #if defined (HAVE_LSTAT) if (S_ISLNK (mode)) { linkok = stat (name, &linkstat) == 0; if (linkok && strncmp (_rl_color_indicator[C_LINK].string, "target", 6) == 0) mode = linkstat.st_mode; } else #endif linkok = 1; } else linkok = -1; /* Is this a nonexistent file? If so, linkok == -1. */ if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL) colored_filetype = C_MISSING; else if (linkok == 0 && S_ISLNK(mode) && _rl_color_indicator[C_ORPHAN].string != NULL) colored_filetype = C_ORPHAN; /* dangling symlink */ else if(stat_ok != 0) { static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS; colored_filetype = filetype_indicator[normal]; //f->filetype]; } else { if (S_ISREG (mode)) { colored_filetype = C_FILE; if ((mode & S_ISUID) != 0 && is_colored (C_SETUID)) colored_filetype = C_SETUID; else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID)) colored_filetype = C_SETGID; else if (is_colored (C_CAP) && 0) //f->has_capability) colored_filetype = C_CAP; else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC)) colored_filetype = C_EXEC; else if ((1 < astat.st_nlink) && is_colored (C_MULTIHARDLINK)) colored_filetype = C_MULTIHARDLINK; } else if (S_ISDIR (mode)) { colored_filetype = C_DIR; #if defined (S_ISVTX) if ((mode & S_ISVTX) && (mode & S_IWOTH) && is_colored (C_STICKY_OTHER_WRITABLE)) colored_filetype = C_STICKY_OTHER_WRITABLE; else #endif if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE)) colored_filetype = C_OTHER_WRITABLE; #if defined (S_ISVTX) else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY)) colored_filetype = C_STICKY; #endif } else if (S_ISLNK (mode)) colored_filetype = C_LINK; else if (S_ISFIFO (mode)) colored_filetype = C_FIFO; else if (S_ISSOCK (mode)) colored_filetype = C_SOCK; else if (S_ISBLK (mode)) colored_filetype = C_BLK; else if (S_ISCHR (mode)) colored_filetype = C_CHR; else { /* Classify a file of some other type as C_ORPHAN. */ colored_filetype = C_ORPHAN; } } /* Check the file's suffix only if still classified as C_FILE. */ ext = NULL; if (colored_filetype == C_FILE) { /* Test if NAME has a recognized suffix. */ len = strlen (name); name += len; /* Pointer to final \0. */ for (ext = _rl_color_ext_list; ext != NULL; ext = ext->next) { if (ext->ext.len <= len && strncmp (name - ext->ext.len, ext->ext.string, ext->ext.len) == 0) break; } } free (filename); /* NULL or savestring return value */ { const struct bin_str *const s = ext ? &(ext->seq) : &_rl_color_indicator[colored_filetype]; if (s->string != NULL) { /* Need to reset so not dealing with attribute combinations */ if (is_colored (C_NORM)) restore_default_color (); _rl_put_indicator (&_rl_color_indicator[C_LEFT]); _rl_put_indicator (s); _rl_put_indicator (&_rl_color_indicator[C_RIGHT]); return 0; } else return 1; } }
int main(int argc, char *argv[]) { char *filename; struct stat sb; int filekind; char *reason; int status; // argument check if (argc != 2) { fprintf(stderr, "Usage: " PROGNAME_S " <device>\n"); return 1; } filename = argv[1]; // set input to unbuffered fflush(NULL); setvbuf(stdin, NULL, _IONBF, 0); // stat check if (stat(filename, &sb) < 0) { errore("Can't stat %.300s", filename); return 1; } filekind = 0; reason = NULL; 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 1; } // open file fd = open(filename, O_RDWR); if (fd < 0 && errno == EBUSY) { fd = open(filename, O_RDONLY); #ifndef NOREADONLYWARN if (fd >= 0) printf("Warning: %.300s opened read-only\n", filename); #endif } if (fd < 0) { errore("Can't open %.300s", filename); return 1; } // (try to) guard against TTY character devices if (filekind == 2) { if (isatty(fd)) { error("%.300s: Is a TTY device", filename); return 1; } } // run sync algorithm status = PROGNAME(); printf("\n"); // close file if (close(fd) != 0) { errore("Error while closing %.300s", filename); return 1; } return status; }
int file_test(const char* name, const char* flags) { struct stat stat_result; if(stat(name, &stat_result)==-1) { //if(flags[0]!=FILE_EXISTS)warn("file_test(\"%s\",\"%s\") failed", name, flags); return 0; } if(flags==NULL || flags[0]=='\0' || flags[1]!='\0') { warn("file_test(\"%s\",\"%s\"), invalid flags", name, flags); } time_t now=time(NULL); switch (flags[0]) { case FILE_READABLE:break; //return stat_result.st_mode & S_IRUSR; case FILE_WRITABLE:break; //return stat_result.st_mode & S_IWUSR; case FILE_EXECUTABLE:break; //return stat_result.st_mode & S_IXUSR; case FILE_OWNED:break; return stat_result.st_uid==geteuid(); case FILE_READABLE_REAL_ID:break; case FILE_WRITABLE_REAL_ID:break; case FILE_EXECUTABLE_REAL_ID:break; case FILE_OWNED_REAL_ID: return stat_result.st_uid==getuid(); case FILE_EXISTS: return 1; case FILE_EMPTY: return stat_result.st_size==0; case FILE_SIZE: return stat_result.st_size; case FILE_PLAIN: return S_ISREG(stat_result.st_mode); case FILE_DIRECTORY: return S_ISDIR(stat_result.st_mode); case FILE_LINK: return S_ISLNK(stat_result.st_mode); case FILE_PIPE:break; case FILE_SOCKET: return S_ISSOCK(stat_result.st_mode); case FILE_BLOCK_DEVICE: return S_ISBLK(stat_result.st_mode); case FILE_CHARACTER_DEVICE: return S_ISCHR(stat_result.st_mode); case FILE_TTY:break; case FILE_SETUID: return stat_result.st_mode & S_ISUID; case FILE_SETGID: return stat_result.st_mode & S_ISGID; case FILE_STICKY: return stat_result.st_mode & S_ISVTX; case FILE_TEXT:break; case FILE_BINARY:break; case FILE_MODIFIED_SECONDS: return now-stat_result.st_mtime; case FILE_ACCESSED_SECONDS: return now-stat_result.st_atime; case FILE_CHANGED_SECONDS: return now-stat_result.st_ctime; default: warn("unknown file test \"%s\"",flags); return 0; } warn("file_test(\"%s\",\"%s\") not implemented yet", name, flags); return 0; }
/* * Fill in the given information structure with the file paths and stat * details of the given file descriptor within the given process (given * within the info structure). * * Returns nonzero on error - error codes are: * * -1 - info or state were NULL * 1 - process does not exist * 2 - readlink on /proc/pid/fd/N failed * 3 - stat or lstat on /proc/pid/fd/N failed * 4 - file descriptor is not opened on a regular file * * If "automatic" is nonzero, then this fd was picked automatically, and so * if it's not readable or not a regular file, no error is displayed and the * function just returns an error code. */ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic) { if (NULL == state) return -1; if (NULL == info) return -1; if (kill(info->watch_pid, 0) != 0) { if (!automatic) pv_error(state, "%s %u: %s", _("pid"), info->watch_pid, strerror(errno)); return 1; } snprintf(info->file_fdinfo, sizeof(info->file_fdinfo) - 1, "/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd); snprintf(info->file_fd, sizeof(info->file_fd) - 1, "/proc/%u/fd/%d", info->watch_pid, info->watch_fd); if (readlink (info->file_fd, info->file_fdpath, sizeof(info->file_fdpath) - 1) < 0) { if (!automatic) pv_error(state, "%s %u: %s %d: %s", _("pid"), info->watch_pid, _("fd"), info->watch_fd, strerror(errno)); return 2; } if (!((0 == stat64(info->file_fd, &(info->sb_fd))) && (0 == lstat64(info->file_fd, &(info->sb_fd_link))))) { if (!automatic) pv_error(state, "%s %u: %s %d: %s: %s", _("pid"), info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath, strerror(errno)); return 3; } info->size = 0; if (S_ISBLK(info->sb_fd.st_mode)) { int fd; /* * Get the size of block devices by opening * them and seeking to the end. */ fd = open64(info->file_fdpath, O_RDONLY); if (fd >= 0) { info->size = lseek64(fd, 0, SEEK_END); close(fd); } else { info->size = 0; } } else if (S_ISREG(info->sb_fd.st_mode)) { if ((info->sb_fd_link.st_mode & S_IWUSR) == 0) { info->size = info->sb_fd.st_size; } } else { if (!automatic) pv_error(state, "%s %u: %s %d: %s: %s", _("pid"), info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath, _("not a regular file or block device")); return 4; } return 0; }
int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { char *tmpstr; struct passwd *pw; struct group *gr; char time[128]; struct tm t; const char *type; /* no stat attributes for data from a buffer, it is just a file */ if(len){ xar_prop_set(f, "type", "file"); return 0; } if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) { xar_file_t tmpf; const char *id = xar_attr_get(f, NULL, "id"); if( !id ) { xar_err_new(x); xar_err_set_file(x, f); xar_err_set_string(x, "stat: No file id for file"); xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); return -1; } tmpf = xar_link_lookup(x, XAR(x)->sbcache.st_dev, XAR(x)->sbcache.st_ino, f); xar_prop_set(f, "type", "hardlink"); if( tmpf ) { const char *id; id = xar_attr_get(tmpf, NULL, "id"); xar_attr_set(f, "type", "link", id); } else { xar_attr_set(f, "type", "link", "original"); } } else { type = filetype_name(XAR(x)->sbcache.st_mode & S_IFMT); xar_prop_set(f, "type", type); } /* Record major/minor device node numbers */ if( S_ISBLK(XAR(x)->sbcache.st_mode) || S_ISCHR(XAR(x)->sbcache.st_mode)) { uint32_t major, minor; char tmpstr[12]; xar_devmake(XAR(x)->sbcache.st_rdev, &major, &minor); memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr)-1, "%u", major); xar_prop_set(f, "device/major", tmpstr); memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr)-1, "%u", minor); xar_prop_set(f, "device/minor", tmpstr); } if( S_ISLNK(XAR(x)->sbcache.st_mode) ) { char link[4096]; struct stat lsb; memset(link, 0, sizeof(link)); readlink(file, link, sizeof(link)-1); xar_prop_set(f, "link", link); if( stat(file, &lsb) != 0 ) { xar_attr_set(f, "link", "type", "broken"); } else { type = filetype_name(lsb.st_mode & S_IFMT); xar_attr_set(f, "link", "type", type); } } asprintf(&tmpstr, "%04o", XAR(x)->sbcache.st_mode & (~S_IFMT)); xar_prop_set(f, "mode", tmpstr); free(tmpstr); asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_uid); xar_prop_set(f, "uid", tmpstr); free(tmpstr); pw = getpwuid(XAR(x)->sbcache.st_uid); if( pw ) xar_prop_set(f, "user", pw->pw_name); asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_gid); xar_prop_set(f, "gid", tmpstr); free(tmpstr); gr = getgrgid(XAR(x)->sbcache.st_gid); if( gr ) xar_prop_set(f, "group", gr->gr_name); gmtime_r(&XAR(x)->sbcache.st_atime, &t); memset(time, 0, sizeof(time)); strftime(time, sizeof(time), "%FT%T", &t); strcat(time, "Z"); xar_prop_set(f, "atime", time); gmtime_r(&XAR(x)->sbcache.st_mtime, &t); memset(time, 0, sizeof(time)); strftime(time, sizeof(time), "%FT%T", &t); strcat(time, "Z"); xar_prop_set(f, "mtime", time); gmtime_r(&XAR(x)->sbcache.st_ctime, &t); memset(time, 0, sizeof(time)); strftime(time, sizeof(time), "%FT%T", &t); strcat(time, "Z"); xar_prop_set(f, "ctime", time); flags_archive(f, &(XAR(x)->sbcache)); aacls(f, file); return 0; }
/* * Read WAV header, leave file seek pointer past WAV header. */ off_t wavsize(int f) { chunk_t chunk; riff_chunk riff; fmt_chunk fmt; struct stat sb; off_t cursor; BOOL gotFormat; mode_t mode; off_t size; long ret = AU_BAD_HEADER; /* * First check if a bad guy tries to call wavsize() * with an unappropriate file descriptor. * return -1 in this case. */ if (isatty(f)) return (-1L); if (fstat(f, &sb) < 0) return (-1L); mode = sb.st_mode & S_IFMT; if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode)) return (-1L); cursor = (off_t)0; gotFormat = FALSE; for (;;) { if (read(f, &chunk, sizeof (chunk)) != sizeof (chunk)) goto err; size = (off_t)le_a_to_u_long(chunk.cksize); if (strncmp((char *)chunk.ckid, WAV_RIFF_MAGIC, 4) == 0) { /* * We found (first) RIFF header. Check if a WAVE * magic follows. Set up size to be able to skip * past this header. */ if (read(f, &riff, sizeof (riff)) != sizeof (riff)) goto err; if (strncmp((char *)riff.wave, WAV_WAVE_MAGIC, 4) != 0) goto err; size = (off_t)sizeof (riff); } else if (strncmp((char *)chunk.ckid, WAV_FMT_MAGIC, 4) == 0) { /* * We found WAVE "fmt " header. Check size (if it is * valid for a WAVE file) and coding whether it is * useable for a CD. */ if (size < (off_t)sizeof (fmt)) goto err; if (sizeof (fmt) != read(f, &fmt, sizeof (fmt))) goto err; if (le_a_to_u_short(fmt.channels) != 2 || le_a_to_u_long(fmt.sample_rate) != 44100 || le_a_to_u_short(fmt.bits_per_sample) != 16) { ret = AU_BAD_CODING; goto err; } gotFormat = TRUE; } else if (strncmp((char *)chunk.ckid, WAV_DATA_MAGIC, 4) == 0) { /* * We found WAVE "data" header. This contains the * size value of the audio part. */ if (!gotFormat) { ret = AU_BAD_CODING; goto err; } if ((cursor + size + sizeof (chunk)) > sb.st_size) size = sb.st_size - (cursor + sizeof (chunk)); return (size); } cursor += size + sizeof (chunk); lseek(f, cursor, SEEK_SET); /* Skip over current chunk */ } err: lseek(f, (off_t)0L, SEEK_SET); return (ret); }
static void statmodeprint(mode_t mode, char *outbuf, int flags) { if (flags & STF_RAW) { sprintf(outbuf, (flags & STF_OCTAL) ? "0%lo" : "%lu", (unsigned long)mode); if (flags & STF_STRING) strcat(outbuf, " ("); } if (flags & STF_STRING) { static const char *modes = "?rwxrwxrwx"; #ifdef __CYGWIN__ static mode_t mflags[9] = { 0 }; #else static const mode_t mflags[9] = { S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH }; #endif const mode_t *mfp = mflags; char pm[11]; int i; #ifdef __CYGWIN__ if (mflags[0] == 0) { mflags[0] = S_IRUSR; mflags[1] = S_IWUSR; mflags[2] = S_IXUSR; mflags[3] = S_IRGRP; mflags[4] = S_IWGRP; mflags[5] = S_IXGRP; mflags[6] = S_IROTH; mflags[7] = S_IWOTH; mflags[8] = S_IXOTH; } #endif if (S_ISBLK(mode)) *pm = 'b'; else if (S_ISCHR(mode)) *pm = 'c'; else if (S_ISDIR(mode)) *pm = 'd'; else if (S_ISDOOR(mode)) *pm = 'D'; else if (S_ISFIFO(mode)) *pm = 'p'; else if (S_ISLNK(mode)) *pm = 'l'; else if (S_ISMPC(mode)) *pm = 'm'; else if (S_ISNWK(mode)) *pm = 'n'; else if (S_ISOFD(mode)) *pm = 'M'; else if (S_ISOFL(mode)) *pm = 'M'; else if (S_ISREG(mode)) *pm = '-'; else if (S_ISSOCK(mode)) *pm = 's'; else *pm = '?'; for (i = 1; i <= 9; i++) pm[i] = (mode & *mfp++) ? modes[i] : '-'; pm[10] = '\0'; if (mode & S_ISUID) pm[3] = (mode & S_IXUSR) ? 's' : 'S'; if (mode & S_ISGID) pm[6] = (mode & S_IXGRP) ? 's' : 'S'; if (mode & S_ISVTX) pm[9] = (mode & S_IXOTH) ? 't' : 'T'; pm[10] = 0; strcat(outbuf, pm); if (flags & STF_RAW) strcat(outbuf, ")"); } }
void dir_crawl(GTree *t, GHashTable *linkhash, GHashTable *userhash, GHashTable *grouphash, char *path) { DIR *dir; struct dirent *dent; struct rdup *directory; struct chown_pack *cp; char *curpath; gchar *lnk; struct stat s; struct rdup pop; struct remove_path rp; dev_t current_dev; size_t curpath_len; /* dir stack */ gint32 d = 0; gint32 dstack_cnt = 1; struct rdup **dirstack = g_malloc(dstack_cnt * D_STACKSIZE * sizeof(struct rdup *)); if (!(dir = opendir(path))) { /* non-dirs are also allowed, check for this, if it isn't give the error */ if (access(path, R_OK) == 0) { g_free(dirstack); return; } msg(_("Cannot enter directory `%s\': %s"), path, strerror(errno)); g_free(dirstack); return; } /* get device */ #ifdef HAVE_DIRFD if (fstat(dirfd(dir), &s) != 0) { #else if (fstat(rdup_dirfd(dir), &s) != 0) { #endif msg(_("Cannot determine holding device of the directory `%s\': %s"), path, strerror(errno)); closedir(dir); g_free(dirstack); return; } current_dev = s.st_dev; while((dent = readdir(dir))) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; if (opt_chown) { if ( !strncmp(dent->d_name, USRGRPINFO, LEN_USRGRPINFO) ) { continue; } } if (strcmp(path, "/") == 0) { curpath = g_strdup_printf("/%s", dent->d_name); curpath_len = strlen(curpath); } else { curpath = g_strdup_printf("%s/%s", path, dent->d_name); curpath_len = strlen(curpath); } if (lstat(curpath, &s) != 0) { msg(_("Could not stat path `%s\': %s"), curpath, strerror(errno)); g_free(curpath); continue; } if (strchr(curpath, '\n')) { msg(_("Newline (\\n) found in path `%s\', skipping"), curpath); g_free(curpath); continue; } if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode) || S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) || S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode) ) { pop.f_name = curpath; pop.f_target = NULL; pop.f_name_size = curpath_len; pop.f_uid = s.st_uid; pop.f_user = lookup_user(userhash, pop.f_uid); pop.f_gid = s.st_gid; pop.f_group = lookup_group(grouphash, pop.f_gid); pop.f_ctime = s.st_ctime; pop.f_mtime = s.st_mtime; pop.f_atime = s.st_atime; pop.f_mode = s.st_mode; pop.f_size = s.st_size; pop.f_dev = s.st_dev; pop.f_rdev = s.st_rdev; pop.f_ino = s.st_ino; pop.f_lnk = 0; if (gfunc_regexp(pregex_list, curpath, curpath_len)) { g_free(curpath); continue; } if (opt_nobackup && !strcmp(dent->d_name, NOBACKUP)) { /* return after seeing .nobackup */ if (opt_verbose > 0) { msg(_("%s found in '%s\'"), NOBACKUP, path); } /* remove all files found in this path */ rp.tree = t; rp.len = strlen(path); rp.path = path; g_tree_foreach(t, gfunc_remove_path, (gpointer)&rp); /* add .nobackup back in */ g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE); g_free(dirstack); closedir(dir); return; } /* hardlinks */ if (s.st_nlink > 1) { if ((lnk = hlink(linkhash, &pop))) { pop.f_target = lnk; pop.f_lnk = 1; } } if (S_ISLNK(s.st_mode)) pop.f_target = slink(&pop); if (S_ISLNK(s.st_mode) || pop.f_lnk) { /* fix the name and the sizes */ pop.f_size = pop.f_name_size; pop.f_name_size += 4 + strlen(pop.f_target); } /* check for USRGRPINFO file */ if ( opt_chown && (cp = chown_parse(path, dent->d_name)) != NULL ) { pop.f_uid = cp->u; pop.f_gid = cp->g; pop.f_user = cp->user; pop.f_group = cp->group; } g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE); if (pop.f_target != NULL) g_free(pop.f_target); g_free(curpath); continue; } else if(S_ISDIR(s.st_mode)) { /* one filesystem */ if (opt_onefilesystem && s.st_dev != current_dev) { msg(_("Not walking into different filesystem `%s\'"), curpath); g_free(curpath); continue; } /* Exclude list */ if (gfunc_regexp(pregex_list, curpath, curpath_len)) { g_free(curpath); continue; } dirstack[d] = g_malloc(sizeof(struct rdup)); dirstack[d]->f_name = g_strdup(curpath); dirstack[d]->f_target = NULL; dirstack[d]->f_name_size = curpath_len; dirstack[d]->f_uid = s.st_uid; dirstack[d]->f_user = lookup_user(userhash, s.st_uid); dirstack[d]->f_gid = s.st_gid; dirstack[d]->f_group = lookup_group(grouphash, s.st_gid); dirstack[d]->f_ctime = s.st_ctime; dirstack[d]->f_mtime = s.st_mtime; dirstack[d]->f_atime = s.st_atime; dirstack[d]->f_mode = s.st_mode; dirstack[d]->f_size = s.st_size; dirstack[d]->f_dev = s.st_dev; dirstack[d]->f_rdev = s.st_rdev; dirstack[d]->f_ino = s.st_ino; dirstack[d]->f_lnk = 0; /* check for USRGRPINFO file */ if ( opt_chown && (cp = chown_parse(curpath, NULL)) != NULL ) { dirstack[d]->f_uid = cp->u; dirstack[d]->f_gid = cp->g; dirstack[d]->f_user = cp->user; dirstack[d]->f_group = cp->group; } if (d++ % D_STACKSIZE == 0) { dirstack = g_realloc(dirstack, ++dstack_cnt * D_STACKSIZE * sizeof(struct rdup *)); } g_free(curpath); continue; } else { if (opt_verbose > 0) { msg(_("Neither file nor directory `%s\'"), curpath); } g_free(curpath); } } closedir(dir); if (opt_atime) { /* reset dirs atime */ if (d > 0 && opt_atime) { struct utimbuf ut; ut.actime = dirstack[d - 1]->f_atime; ut.modtime = dirstack[d - 1]->f_mtime; if (utime(dirstack[d - 1]->f_name, &ut) == -1) msg(_("Failed to reset atime: '%s\': %s"), dirstack[d - 1]->f_name, strerror(errno)); } } while (d > 0) { directory = dirstack[--d]; g_tree_insert(t, (gpointer) entry_dup(directory), VALUE); /* recurse */ /* potentially expensive operation. Better would be to when we hit * .nobackup to go up the tree and delete some nodes.... or not */ dir_crawl(t, linkhash, userhash, grouphash, directory->f_name); entry_free(directory); } g_free(dirstack); return; }
int is_blkdev(int fd) { struct stat st; return (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode)); }
int do_sync_pull(const char *rpath, const char *lpath) { unsigned mode; struct stat st; int fd; fd = sdb_connect("sync:"); if(fd < 0) { fprintf(stderr,"error: %s\n", sdb_error()); return 1; } if(sync_readmode(fd, rpath, &mode)) { return 1; } if(mode == 0) { fprintf(stderr,"remote object '%s' does not exist\n", rpath); return 1; } if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) { if(stat(lpath, &st) == 0) { if(S_ISDIR(st.st_mode)) { /* if we're copying a remote file to a local directory, ** we *really* want to copy to localdir + "/" + remotefilename */ const char *name = sdb_dirstop(rpath); if(name == 0) { name = rpath; } else { name++; } int tmplen = strlen(name) + strlen(lpath) + 2; char *tmp = malloc(tmplen); if(tmp == 0) return 1; snprintf(tmp, tmplen, "%s/%s", lpath, name); lpath = tmp; } } BEGIN(); if(sync_recv(fd, rpath, lpath)) { return 1; } else { END(); sync_quit(fd); return 0; } } else if(S_ISDIR(mode)) { BEGIN(); if (copy_remote_dir_local(fd, rpath, lpath, 0)) { return 1; } else { END(); sync_quit(fd); return 0; } } else { fprintf(stderr,"remote object '%s' not a file or directory\n", rpath); return 1; } }
/* get size in bytes */ int blkdev_get_size(int fd, unsigned long long *bytes) { #ifdef DKIOCGETBLOCKCOUNT /* Apple Darwin */ if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) { *bytes <<= 9; return 0; } #endif #ifdef BLKGETSIZE64 { #ifdef __linux__ int ver = get_linux_version(); /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */ if (ver >= KERNEL_VERSION (2,6,0) || (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0))) #endif if (ioctl(fd, BLKGETSIZE64, bytes) >= 0) return 0; } #endif /* BLKGETSIZE64 */ #ifdef BLKGETSIZE { unsigned long size; if (ioctl(fd, BLKGETSIZE, &size) >= 0) { *bytes = ((unsigned long long)size << 9); return 0; } } #endif /* BLKGETSIZE */ #ifdef DIOCGMEDIASIZE /* FreeBSD */ if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0) return 0; #endif #ifdef FDGETPRM { struct floppy_struct this_floppy; if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { *bytes = ((unsigned long long) this_floppy.size) << 9; return 0; } } #endif /* FDGETPRM */ #if defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) { /* * This code works for FreeBSD 4.11 i386, except for the full device * (such as /dev/ad0). It doesn't work properly for newer FreeBSD * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE * above however. * * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw, * character) devices, so we need to check for S_ISCHR, too. */ int part = -1; struct disklabel lab; struct partition *pp; struct stat st; if ((fstat(fd, &st) >= 0) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) part = st.st_rdev & 7; if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { pp = &lab.d_partitions[part]; if (pp->p_size) { *bytes = pp->p_size << 9; return 0; } } } #endif /* defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) */ { struct stat st; if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { *bytes = st.st_size; return 0; } if (!S_ISBLK(st.st_mode)) return -1; } *bytes = blkdev_find_size(fd); return 0; }
int main(int argc, char *argv[]) { int c; char * raw_name; char * block_name; int err; int block_major, block_minor; int i, rc; struct stat statbuf; setlocale(LC_MESSAGES, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); progname = argv[0]; while ((c = getopt(argc, argv, "ahq")) != -1) { switch (c) { case 'a': do_query_all = 1; break; case 'h': usage(0); case 'q': do_query = 1; break; default: usage(1); } } /* * Check for, and open, the master raw device, /dev/raw */ open_raw_ctl(); if (do_query_all) { if (optind < argc) usage(1); for (i = 1; i < RAW_NR_MINORS; i++) query(i, NULL, 1); exit(0); } /* * It's a bind or a single query. Either way we need a raw device. */ if (optind >= argc) usage(1); raw_name = argv[optind++]; /* * try to check the device name before stat(), because on systems with * udev the raw0 causes a create udev event for char 162/0, which * causes udev to *remove* /dev/rawctl */ rc = sscanf(raw_name, RAWDEVDIR "raw%d", &raw_minor); if (rc != 1) usage(1); if (raw_minor == 0) { fprintf (stderr, _("Device '%s' is the control raw device " "(use raw<N> where <N> is greater than zero)\n"), raw_name); exit(2); } if (do_query) return query(raw_minor, raw_name, 0); /* * It's not a query, so we still have some parsing to do. Have * we been given a block device filename or a major/minor pair? */ switch (argc - optind) { case 1: block_name = argv[optind]; err = stat(block_name, &statbuf); if (err) { fprintf (stderr, _("Cannot locate block device '%s' (%s)\n"), block_name, strerror(errno)); exit(2); } if (!S_ISBLK(statbuf.st_mode)) { fprintf (stderr, _("Device '%s' is not a block device\n"), block_name); exit(2); } block_major = major(statbuf.st_rdev); block_minor = minor(statbuf.st_rdev); break; case 2: block_major = strtol(argv[optind], 0, 0); block_minor = strtol(argv[optind+1], 0, 0); break; default: block_major = block_minor = 0; /* just to keep gcc happy */ usage(1); } return bind(raw_minor, block_major, block_minor); return 0; }
/***************************************************************************** * ioctl_Open: Opens a VCD device or file and returns an opaque handle *****************************************************************************/ vcddev_t *ioctl_Open( vlc_object_t *p_this, const char *psz_dev ) { int i_ret; int b_is_file; vcddev_t *p_vcddev; #if !defined( WIN32 ) && !defined( __OS2__ ) struct stat fileinfo; #endif if( !psz_dev ) return NULL; /* * Initialize structure with default values */ p_vcddev = malloc( sizeof(*p_vcddev) ); if( p_vcddev == NULL ) return NULL; p_vcddev->i_vcdimage_handle = -1; p_vcddev->psz_dev = NULL; b_is_file = 1; /* * Check if we are dealing with a device or a file (vcd image) */ #if defined( WIN32 ) || defined( __OS2__ ) if( (strlen( psz_dev ) == 2 && psz_dev[1] == ':') ) { b_is_file = 0; } #else if( vlc_stat( psz_dev, &fileinfo ) < 0 ) { free( p_vcddev ); return NULL; } /* Check if this is a block/char device */ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) ) b_is_file = 0; #endif if( b_is_file ) { i_ret = OpenVCDImage( p_this, psz_dev, p_vcddev ); } else { /* * open the vcd device */ #ifdef WIN32 i_ret = win32_vcd_open( p_this, psz_dev, p_vcddev ); #elif defined( __OS2__ ) i_ret = os2_vcd_open( p_this, psz_dev, p_vcddev ); #else p_vcddev->i_device_handle = -1; p_vcddev->i_device_handle = vlc_open( psz_dev, O_RDONLY | O_NONBLOCK ); i_ret = (p_vcddev->i_device_handle == -1) ? -1 : 0; #endif } if( i_ret == 0 ) { p_vcddev->psz_dev = (char *)strdup( psz_dev ); } else { free( p_vcddev ); p_vcddev = NULL; } return p_vcddev; }
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); }
int test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2, int do_eval) { int res; int not; struct stat b1, b2; if (!do_eval) return 0; switch ((int) op) { /* * Unary Operators */ case TO_STNZE: /* -n */ return *opnd1 != '\0'; case TO_STZER: /* -z */ return *opnd1 == '\0'; case TO_OPTION: /* -o */ if ((not = *opnd1 == '!')) opnd1++; if ((res = option(opnd1)) < 0) res = 0; else { res = Flag(res); if (not) res = !res; } return res; case TO_FILRD: /* -r */ return test_eaccess(opnd1, R_OK) == 0; case TO_FILWR: /* -w */ return test_eaccess(opnd1, W_OK) == 0; case TO_FILEX: /* -x */ return test_eaccess(opnd1, X_OK) == 0; case TO_FILAXST: /* -a */ return test_stat(opnd1, &b1) == 0; case TO_FILEXST: /* -e */ /* at&t ksh does not appear to do the /dev/fd/ thing for * this (unless the os itself handles it) */ return stat(opnd1, &b1) == 0; case TO_FILREG: /* -r */ return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode); case TO_FILID: /* -d */ return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode); case TO_FILCDEV: /* -c */ return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode); case TO_FILBDEV: /* -b */ return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode); case TO_FILFIFO: /* -p */ return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode); case TO_FILSYM: /* -h -L */ return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode); case TO_FILSOCK: /* -S */ return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode); case TO_FILCDF:/* -H HP context dependent files (directories) */ return 0; case TO_FILSETU: /* -u */ return test_stat(opnd1, &b1) == 0 && (b1.st_mode & S_ISUID) == S_ISUID; case TO_FILSETG: /* -g */ return test_stat(opnd1, &b1) == 0 && (b1.st_mode & S_ISGID) == S_ISGID; case TO_FILSTCK: /* -k */ return test_stat(opnd1, &b1) == 0 && (b1.st_mode & S_ISVTX) == S_ISVTX; case TO_FILGZ: /* -s */ return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L; case TO_FILTT: /* -t */ if (opnd1 && !bi_getn(opnd1, &res)) { te->flags |= TEF_ERROR; res = 0; } else { /* generate error if in FPOSIX mode? */ res = isatty(opnd1 ? res : 0); } return res; case TO_FILUID: /* -O */ return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid; case TO_FILGID: /* -G */ return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid(); /* * Binary Operators */ case TO_STEQL: /* = */ if (te->flags & TEF_DBRACKET) return gmatch(opnd1, opnd2, false); return strcmp(opnd1, opnd2) == 0; case TO_STNEQ: /* != */ if (te->flags & TEF_DBRACKET) return !gmatch(opnd1, opnd2, false); return strcmp(opnd1, opnd2) != 0; case TO_STLT: /* < */ return strcmp(opnd1, opnd2) < 0; case TO_STGT: /* > */ return strcmp(opnd1, opnd2) > 0; case TO_INTEQ: /* -eq */ case TO_INTNE: /* -ne */ case TO_INTGE: /* -ge */ case TO_INTGT: /* -gt */ case TO_INTLE: /* -le */ case TO_INTLT: /* -lt */ { long v1, v2; if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) || !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) { /* error already printed.. */ te->flags |= TEF_ERROR; return 1; } switch ((int) op) { case TO_INTEQ: return v1 == v2; case TO_INTNE: return v1 != v2; case TO_INTGE: return v1 >= v2; case TO_INTGT: return v1 > v2; case TO_INTLE: return v1 <= v2; case TO_INTLT: return v1 < v2; } } case TO_FILNT: /* -nt */ { int s2; /* ksh88/ksh93 succeed if file2 can't be stated * (subtly different from `does not exist'). */ return stat(opnd1, &b1) == 0 && (((s2 = stat(opnd2, &b2)) == 0 && b1.st_mtime > b2.st_mtime) || s2 < 0); } case TO_FILOT: /* -ot */ { int s1; /* ksh88/ksh93 succeed if file1 can't be stated * (subtly different from `does not exist'). */ return stat(opnd2, &b2) == 0 && (((s1 = stat(opnd1, &b1)) == 0 && b1.st_mtime < b2.st_mtime) || s1 < 0); } case TO_FILEQ: /* -ef */ return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 && b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino; } (*te->error)(te, 0, "internal error: unknown op"); return 1; }
dvd_reader_t *DVDOpen( const char *path ) { struct stat fileinfo; int ret, have_css; char *dev_name = NULL; int internal_errno = 0; int verbose; if( path == NULL ) { errno = EINVAL; return NULL; } verbose = get_verbose(); #ifdef WIN32 /* Stat doesn't work on devices under mingwin/cygwin. */ if( path[0] && path[1] == ':' && path[2] == '\0' ) { /* Don't try to stat the file */ fileinfo.st_mode = S_IFBLK; } else #endif { ret = stat( path, &fileinfo ); if( ret < 0 ) { int tmp_errno = errno; /* If we can't stat the file, give up */ if(verbose >= 1) { fprintf( stderr, "libdvdread: Can't stat '%s': %s\n", path, strerror(errno)); } errno = tmp_errno; return NULL; } } /* Try to open libdvdcss or fall back to standard functions */ have_css = dvdinput_setup(); /* First check if this is a block/char device or a file*/ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) || S_ISREG( fileinfo.st_mode ) ) { /** * Block devices and regular files are assumed to be DVD-Video images. */ dvd_reader_t *dvd = NULL; #if defined(__sun) dev_name = sun_block2char( path ); #elif defined(SYS_BSD) dev_name = bsd_block2char( path ); #else dev_name = strdup( path ); #endif dvd = DVDOpenImageFile( dev_name, have_css ); free( dev_name ); return dvd; } else if( S_ISDIR( fileinfo.st_mode ) ) { dvd_reader_t *auth_drive = 0; char *path_copy; #if defined(SYS_BSD) struct fstab* fe; #elif defined(__sun) || defined(__linux__) FILE *mntfile; #endif /* XXX: We should scream real loud here. */ if( !(path_copy = strdup( path ) ) ) return 0; #ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */ /* Resolve any symlinks and get the absolut dir name. */ { char *new_path; char *current_path; current_path = malloc(PATH_MAX); if(current_path) { if(!getcwd(current_path, PATH_MAX)) { free(current_path); current_path = NULL; } } if(current_path) { chdir( path_copy ); new_path = malloc(PATH_MAX); if(new_path) { if(!getcwd(new_path, PATH_MAX )) { free(new_path); new_path = NULL; } } chdir(current_path); free(current_path); if( new_path ) { free( path_copy ); path_copy = new_path; } } } #endif /** * If we're being asked to open a directory, check if that directory * is the mountpoint for a DVD-ROM which we can use instead. */ if( strlen( path_copy ) > 1 ) { if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { path_copy[ strlen( path_copy ) - 1 ] = '\0'; } } if( strlen( path_copy ) >= 9 ) { if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), "/video_ts" ) ) { path_copy[ strlen( path_copy ) - 9 ] = '\0'; if(path_copy[0] == '\0') { path_copy[0] = '/'; path_copy[1] = '\0'; } } } #if defined(SYS_BSD) if( ( fe = getfsfile( path_copy ) ) ) { dev_name = bsd_block2char( fe->fs_spec ); if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s%s\n", dev_name, fe->fs_file, have_css ? " for CSS authentication" : ""); } auth_drive = DVDOpenImageFile( dev_name, have_css ); if(!auth_drive) { internal_errno = errno; } } #elif defined(__sun) mntfile = fopen( MNTTAB, "r" ); if( mntfile ) { struct mnttab mp; int res; while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { dev_name = sun_block2char( mp.mnt_special ); if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s%s\n", dev_name, mp.mnt_mountp, have_css ? " for CSS authentication" : ""); } auth_drive = DVDOpenImageFile( dev_name, have_css ); if(!auth_drive) { internal_errno = errno; } break; } } fclose( mntfile ); } #elif defined(__linux__) mntfile = fopen( MOUNTED, "r" ); if( mntfile ) { struct mntent *me; while( ( me = getmntent( mntfile ) ) ) { if( !strcmp( me->mnt_dir, path_copy ) ) { if(verbose >= 1) { fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s%s\n", me->mnt_fsname, me->mnt_dir, have_css ? " for CSS authentication" : ""); } auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); if(!auth_drive) { internal_errno = errno; } dev_name = strdup(me->mnt_fsname); break; } } fclose( mntfile ); } #endif if( !dev_name ) { if(verbose >= 1) { fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); } } else if( !auth_drive ) { if(verbose >= 1) { fprintf( stderr, "libdvdread: Device %s inaccessible%s: %s\n", dev_name, have_css ? ", CSS authentication not available" : "", strerror(internal_errno)); } } free( dev_name ); free( path_copy ); /** * If we've opened a drive, just use that. */ if( auth_drive ) { return auth_drive; } /** * Otherwise, we now try to open the directory tree instead. */ return DVDOpenPath( path ); } /* If it's none of the above, screw it. */ if(verbose >= 1) { fprintf( stderr, "libdvdread: Could not open %s\n", path ); } return 0; }
int do_create (ext2_filsys e2fs, const char *path, mode_t mode, dev_t dev, const char *fastsymlink) { int rt; time_t tm; errcode_t rc; char *p_path; char *r_path; ext2_ino_t ino; struct ext2_inode inode; ext2_ino_t n_ino; struct fuse_context *ctx; debugf("enter"); debugf("path = %s, mode: 0%o", path, mode); rt=do_check_split(path, &p_path, &r_path); debugf("parent: %s, child: %s", p_path, r_path); rt = do_readinode(e2fs, p_path, &ino, &inode); if (rt) { debugf("do_readinode(%s, &ino, &inode); failed", p_path); free_split(p_path, r_path); return rt; } rc = ext2fs_new_inode(e2fs, ino, mode, 0, &n_ino); if (rc) { debugf("ext2fs_new_inode(ep.fs, ino, mode, 0, &n_ino); failed"); return -ENOMEM; } do { debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", ino, r_path, n_ino, do_modetoext2lag(mode)); rc = ext2fs_link(e2fs, ino, r_path, n_ino, do_modetoext2lag(mode)); if (rc == EXT2_ET_DIR_NO_SPACE) { debugf("calling ext2fs_expand_dir(e2fs, &d)", ino); if (ext2fs_expand_dir(e2fs, ino)) { debugf("error while expanding directory %s (%d)", p_path, ino); free_split(p_path, r_path); return -ENOSPC; } } } while (rc == EXT2_ET_DIR_NO_SPACE); if (rc) { debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", ino, r_path, n_ino, do_modetoext2lag(mode)); free_split(p_path, r_path); return -EIO; } if (ext2fs_test_inode_bitmap(e2fs->inode_map, n_ino)) { debugf("inode already set"); } ext2fs_inode_alloc_stats2(e2fs, n_ino, +1, 0); memset(&inode, 0, sizeof(inode)); tm = e2fs->now ? e2fs->now : time(NULL); inode.i_mode = mode; inode.i_atime = inode.i_ctime = inode.i_mtime = tm; inode.i_links_count = 1; inode.i_size = 0; ctx = fuse_get_context(); if (ctx) { inode.i_uid = ctx->uid; inode.i_gid = ctx->gid; } if (S_ISCHR(mode) || S_ISBLK(mode)) { if (old_valid_dev(dev)) inode.i_block[0]= ext2fs_cpu_to_le32(old_encode_dev(dev)); else inode.i_block[1]= ext2fs_cpu_to_le32(new_encode_dev(dev)); } if (S_ISLNK(mode) && fastsymlink != NULL) { inode.i_size = strlen(fastsymlink); strncpy((char *)&(inode.i_block[0]),fastsymlink, (EXT2_N_BLOCKS * sizeof(inode.i_block[0]))); } rc = ext2fs_write_new_inode(e2fs, n_ino, &inode); if (rc) { debugf("ext2fs_write_new_inode(e2fs, n_ino, &inode);"); free_split(p_path, r_path); return -EIO; } /* update parent dir */ rt = do_readinode(e2fs, p_path, &ino, &inode); if (rt) { debugf("do_readinode(%s, &ino, &inode); dailed", p_path); free_split(p_path, r_path); return -EIO; } inode.i_ctime = inode.i_mtime = tm; rc = ext2fs_write_inode(e2fs, ino, &inode); if (rc) { debugf("ext2fs_write_inode(e2fs, ino, &inode); failed"); free_split(p_path, r_path); return -EIO; } free_split(p_path, r_path); debugf("leave"); return 0; }
/* * Check to see if the special file named 'device' is mounted. */ void check_mtab(const char *device) /* /dev/hd1 or whatever */ { #if defined(__minix) int n, r; struct stat sb; char dev[PATH_MAX], mount_point[PATH_MAX], type[MNTNAMELEN], flags[MNTFLAGLEN]; r= stat(device, &sb); if (r == -1) { if (errno == ENOENT) return; /* Does not exist, and therefore not mounted. */ err(1, "stat %s failed", device); } if (!S_ISBLK(sb.st_mode)) { /* Not a block device and therefore not mounted. */ return; } if (load_mtab(__UNCONST("mkfs")) < 0) return; while (1) { n = get_mtab_entry(dev, mount_point, type, flags); if (n < 0) return; if (strcmp(device, dev) == 0) { /* Can't mkfs on top of a mounted file system. */ errx(1, "%s is mounted on %s", device, mount_point); } } #elif defined(__linux__) /* XXX: this code is copyright Theodore T'so and distributed under the GPLv2. Rewrite. */ struct mntent *mnt; struct stat st_buf; dev_t file_dev=0, file_rdev=0; ino_t file_ino=0; FILE *f; int fd; char *mtab_file = "/proc/mounts"; if ((f = setmntent (mtab_file, "r")) == NULL) goto error; if (stat(device, &st_buf) == 0) { if (S_ISBLK(st_buf.st_mode)) { file_rdev = st_buf.st_rdev; } else { file_dev = st_buf.st_dev; file_ino = st_buf.st_ino; } } while ((mnt = getmntent (f)) != NULL) { if (strcmp(device, mnt->mnt_fsname) == 0) break; if (stat(mnt->mnt_fsname, &st_buf) == 0) { if (S_ISBLK(st_buf.st_mode)) { if (file_rdev && (file_rdev == st_buf.st_rdev)) break; } else { if (file_dev && ((file_dev == st_buf.st_dev) && (file_ino == st_buf.st_ino))) break; } } } if (mnt == NULL) { /* * Do an extra check to see if this is the root device. We * can't trust /etc/mtab, and /proc/mounts will only list * /dev/root for the root filesystem. Argh. Instead we * check if the given device has the same major/minor number * as the device that the root directory is on. */ if (file_rdev && stat("/", &st_buf) == 0) { if (st_buf.st_dev == file_rdev) { goto is_root; } } goto test_busy; } /* Validate the entry in case /etc/mtab is out of date */ /* * We need to be paranoid, because some broken distributions * (read: Slackware) don't initialize /etc/mtab before checking * all of the non-root filesystems on the disk. */ if (stat(mnt->mnt_dir, &st_buf) < 0) { if (errno == ENOENT) { goto test_busy; } goto error; } if (file_rdev && (st_buf.st_dev != file_rdev)) { goto error; } fprintf(stderr, "Device %s is mounted, exiting\n", device); exit(-1); /* * Check to see if we're referring to the root filesystem. * If so, do a manual check to see if we can open /etc/mtab * read/write, since if the root is mounted read/only, the * contents of /etc/mtab may not be accurate. */ if (!strcmp(mnt->mnt_dir, "/")) { is_root: fprintf(stderr, "Device %s is mounted as root file system!\n", device); exit(-1); } test_busy: endmntent (f); if ((stat(device, &st_buf) != 0) || !S_ISBLK(st_buf.st_mode)) return; fd = open(device, O_RDONLY | O_EXCL); if (fd < 0) { if (errno == EBUSY) { fprintf(stderr, "Device %s is used by the system\n", device); exit(-1); } } else close(fd); return; error: endmntent (f); fprintf(stderr, "Error while checking if device %s is mounted\n", device); exit(-1); #else (void) device; /* shut up warnings about unused variable... */ #endif }
static int nfs_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_diropargs arg = { .fh = NFS_FH(dir), .name = name->name, .len = name->len }; struct nfs_diropok res = { .fh = fhandle, .fattr = fattr }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_LOOKUP], .rpc_argp = &arg, .rpc_resp = &res, }; int status; dprintk("NFS call lookup %s\n", name->name); nfs_fattr_init(fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); dprintk("NFS reply lookup: %d\n", status); return status; } static int nfs_proc_readlink(struct inode *inode, struct page *page, unsigned int pgbase, unsigned int pglen) { struct nfs_readlinkargs args = { .fh = NFS_FH(inode), .pgbase = pgbase, .pglen = pglen, .pages = &page }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_READLINK], .rpc_argp = &args, }; int status; dprintk("NFS call readlink\n"); status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); dprintk("NFS reply readlink: %d\n", status); return status; } static int nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags, struct nameidata *nd) { struct nfs_fh fhandle; struct nfs_fattr fattr; struct nfs_createargs arg = { .fh = NFS_FH(dir), .name = dentry->d_name.name, .len = dentry->d_name.len, .sattr = sattr }; struct nfs_diropok res = { .fh = &fhandle, .fattr = &fattr }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_CREATE], .rpc_argp = &arg, .rpc_resp = &res, }; int status; nfs_fattr_init(&fattr); dprintk("NFS call create %s\n", dentry->d_name.name); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); if (status == 0) status = nfs_instantiate(dentry, &fhandle, &fattr); dprintk("NFS reply create: %d\n", status); return status; } /* * In NFSv2, mknod is grafted onto the create call. */ static int nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dev_t rdev) { struct nfs_fh fhandle; struct nfs_fattr fattr; struct nfs_createargs arg = { .fh = NFS_FH(dir), .name = dentry->d_name.name, .len = dentry->d_name.len, .sattr = sattr }; struct nfs_diropok res = { .fh = &fhandle, .fattr = &fattr }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_CREATE], .rpc_argp = &arg, .rpc_resp = &res, }; int status, mode; dprintk("NFS call mknod %s\n", dentry->d_name.name); mode = sattr->ia_mode; if (S_ISFIFO(mode)) { sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR; sattr->ia_valid &= ~ATTR_SIZE; } else if (S_ISCHR(mode) || S_ISBLK(mode)) { sattr->ia_valid |= ATTR_SIZE; sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ } nfs_fattr_init(&fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); if (status == -EINVAL && S_ISFIFO(mode)) { sattr->ia_mode = mode; nfs_fattr_init(&fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); } if (status == 0) status = nfs_instantiate(dentry, &fhandle, &fattr); dprintk("NFS reply mknod: %d\n", status); return status; } static int nfs_proc_remove(struct inode *dir, struct qstr *name) { struct nfs_removeargs arg = { .fh = NFS_FH(dir), .name.len = name->len, .name.name = name->name, }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_REMOVE], .rpc_argp = &arg, }; int status; dprintk("NFS call remove %s\n", name->name); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); dprintk("NFS reply remove: %d\n", status); return status; } static void nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) { msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE]; } static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) { if (nfs_async_handle_expired_key(task)) return 0; nfs_mark_for_revalidate(dir); return 1; } static int nfs_proc_rename(struct inode *old_dir, struct qstr *old_name, struct inode *new_dir, struct qstr *new_name) { struct nfs_renameargs arg = { .fromfh = NFS_FH(old_dir), .fromname = old_name->name, .fromlen = old_name->len, .tofh = NFS_FH(new_dir), .toname = new_name->name, .tolen = new_name->len }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_RENAME], .rpc_argp = &arg, }; int status; dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0); nfs_mark_for_revalidate(old_dir); nfs_mark_for_revalidate(new_dir); dprintk("NFS reply rename: %d\n", status); return status; } static int nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) { struct nfs_linkargs arg = { .fromfh = NFS_FH(inode), .tofh = NFS_FH(dir), .toname = name->name, .tolen = name->len }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_LINK], .rpc_argp = &arg, }; int status; dprintk("NFS call link %s\n", name->name); status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); nfs_mark_for_revalidate(inode); nfs_mark_for_revalidate(dir); dprintk("NFS reply link: %d\n", status); return status; } static int nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, unsigned int len, struct iattr *sattr) { struct nfs_fh fhandle; struct nfs_fattr fattr; struct nfs_symlinkargs arg = { .fromfh = NFS_FH(dir), .fromname = dentry->d_name.name, .fromlen = dentry->d_name.len, .pages = &page, .pathlen = len, .sattr = sattr }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], .rpc_argp = &arg, }; int status; if (len > NFS2_MAXPATHLEN) return -ENAMETOOLONG; dprintk("NFS call symlink %s\n", dentry->d_name.name); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); /* * V2 SYMLINK requests don't return any attributes. Setting the * filehandle size to zero indicates to nfs_instantiate that it * should fill in the data with a LOOKUP call on the wire. */ if (status == 0) { nfs_fattr_init(&fattr); fhandle.size = 0; status = nfs_instantiate(dentry, &fhandle, &fattr); } dprintk("NFS reply symlink: %d\n", status); return status; } static int nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) { struct nfs_fh fhandle; struct nfs_fattr fattr; struct nfs_createargs arg = { .fh = NFS_FH(dir), .name = dentry->d_name.name, .len = dentry->d_name.len, .sattr = sattr }; struct nfs_diropok res = { .fh = &fhandle, .fattr = &fattr }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], .rpc_argp = &arg, .rpc_resp = &res, }; int status; dprintk("NFS call mkdir %s\n", dentry->d_name.name); nfs_fattr_init(&fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); if (status == 0) status = nfs_instantiate(dentry, &fhandle, &fattr); dprintk("NFS reply mkdir: %d\n", status); return status; } static int nfs_proc_rmdir(struct inode *dir, struct qstr *name) { struct nfs_diropargs arg = { .fh = NFS_FH(dir), .name = name->name, .len = name->len }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_RMDIR], .rpc_argp = &arg, }; int status; dprintk("NFS call rmdir %s\n", name->name); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); dprintk("NFS reply rmdir: %d\n", status); return status; } /* * The READDIR implementation is somewhat hackish - we pass a temporary * buffer to the encode function, which installs it in the receive * the receive iovec. The decode function just parses the reply to make * sure it is syntactically correct; the entries itself are decoded * from nfs_readdir by calling the decode_entry function directly. */ static int nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page *page, unsigned int count, int plus) { struct inode *dir = dentry->d_inode; struct nfs_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, .count = count, .pages = &page, }; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_READDIR], .rpc_argp = &arg, .rpc_cred = cred, }; int status; dprintk("NFS call readdir %d\n", (unsigned int)cookie); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_invalidate_atime(dir); dprintk("NFS reply readdir: %d\n", status); return status; } static int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *stat) { struct nfs2_fsstat fsinfo; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_STATFS], .rpc_argp = fhandle, .rpc_resp = &fsinfo, }; int status; dprintk("NFS call statfs\n"); nfs_fattr_init(stat->fattr); status = rpc_call_sync(server->client, &msg, 0); dprintk("NFS reply statfs: %d\n", status); if (status) goto out; stat->tbytes = (u64)fsinfo.blocks * fsinfo.bsize; stat->fbytes = (u64)fsinfo.bfree * fsinfo.bsize; stat->abytes = (u64)fsinfo.bavail * fsinfo.bsize; stat->tfiles = 0; stat->ffiles = 0; stat->afiles = 0; out: return status; } static int nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { struct nfs2_fsstat fsinfo; struct rpc_message msg = { .rpc_proc = &nfs_procedures[NFSPROC_STATFS], .rpc_argp = fhandle, .rpc_resp = &fsinfo, }; int status; dprintk("NFS call fsinfo\n"); nfs_fattr_init(info->fattr); status = rpc_call_sync(server->client, &msg, 0); dprintk("NFS reply fsinfo: %d\n", status); if (status) goto out; info->rtmax = NFS_MAXDATA; info->rtpref = fsinfo.tsize; info->rtmult = fsinfo.bsize; info->wtmax = NFS_MAXDATA; info->wtpref = fsinfo.tsize; info->wtmult = fsinfo.bsize; info->dtpref = fsinfo.tsize; info->maxfilesize = 0x7FFFFFFF; info->lease_time = 0; out: return status; } static int nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_pathconf *info) { info->max_link = 0; info->max_namelen = NFS2_MAXNAMLEN; return 0; } static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) { if (nfs_async_handle_expired_key(task)) return -EAGAIN; nfs_invalidate_atime(data->inode); if (task->tk_status >= 0) { nfs_refresh_inode(data->inode, data->res.fattr); /* Emulate the eof flag, which isn't normally needed in NFSv2 * as it is guaranteed to always return the file attributes */ if (data->args.offset + data->args.count >= data->res.fattr->size) data->res.eof = 1; } return 0; } static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) { msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; } static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) { if (nfs_async_handle_expired_key(task)) return -EAGAIN; if (task->tk_status >= 0) nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); return 0; } static void nfs_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) { /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ data->args.stable = NFS_FILE_SYNC; msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; } static void nfs_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { BUG(); } static int nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) { struct inode *inode = filp->f_path.dentry->d_inode; return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); } /* Helper functions for NFS lock bounds checking */ #define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL) static int nfs_lock_check_bounds(const struct file_lock *fl) { __s32 start, end; start = (__s32)fl->fl_start; if ((loff_t)start != fl->fl_start) goto out_einval; if (fl->fl_end != OFFSET_MAX) { end = (__s32)fl->fl_end; if ((loff_t)end != fl->fl_end) goto out_einval; } else end = NFS_LOCK32_OFFSET_MAX; if (start < 0 || start > end) goto out_einval; return 0; out_einval: return -EINVAL; } const struct nfs_rpc_ops nfs_v2_clientops = { .version = 2, /* protocol version */ .dentry_ops = &nfs_dentry_operations, .dir_inode_ops = &nfs_dir_inode_operations, .file_inode_ops = &nfs_file_inode_operations, .getroot = nfs_proc_get_root, .getattr = nfs_proc_getattr, .setattr = nfs_proc_setattr, .lookup = nfs_proc_lookup, .access = NULL, /* access */ .readlink = nfs_proc_readlink, .create = nfs_proc_create, .remove = nfs_proc_remove, .unlink_setup = nfs_proc_unlink_setup, .unlink_done = nfs_proc_unlink_done, .rename = nfs_proc_rename, .link = nfs_proc_link, .symlink = nfs_proc_symlink, .mkdir = nfs_proc_mkdir, .rmdir = nfs_proc_rmdir, .readdir = nfs_proc_readdir, .mknod = nfs_proc_mknod, .statfs = nfs_proc_statfs, .fsinfo = nfs_proc_fsinfo, .pathconf = nfs_proc_pathconf, .decode_dirent = nfs_decode_dirent, .read_setup = nfs_proc_read_setup, .read_done = nfs_read_done, .write_setup = nfs_proc_write_setup, .write_done = nfs_write_done, .commit_setup = nfs_proc_commit_setup, .lock = nfs_proc_lock, .lock_check_bounds = nfs_lock_check_bounds, .close_context = nfs_close_context, };
/* Turn file (or device node) into class name */ static int affinity_file(struct bitmask *mask, char *cls, const char *file) { struct stat st; DIR *dir; int n; unsigned maj = 0, min = 0; dev_t d; struct dirent de, *dep; cls = "block"; char fn[sizeof("/sys/class/") + strlen(cls)]; if (stat(file, &st) < 0) { numa_warn(W_blockdev1, "Cannot stat file %s", file); return -1; } d = st.st_dev; if (S_ISCHR(st.st_mode)) { /* Better choice than misc? Most likely misc will not work anyways unless the kernel is fixed. */ cls = "misc"; d = st.st_rdev; } else if (S_ISBLK(st.st_mode)) d = st.st_rdev; sprintf(fn, "/sys/class/%s", cls); dir = opendir(fn); if (!dir) { numa_warn(W_blockdev2, "Cannot enumerate %s devices in sysfs", cls); return -1; } while (readdir_r(dir, &de, &dep) == 0 && dep) { char *name = dep->d_name; if (*name == '.') continue; char *dev; char fn2[sizeof("/sys/class/block//dev") + strlen(name)]; n = -1; if (sprintf(fn2, "/sys/class/block/%s/dev", name) < 0) break; dev = sysfs_read(fn2); if (dev) { n = sscanf(dev, "%u:%u", &maj, &min); free(dev); } if (n != 2) { numa_warn(W_blockdev3, "Cannot parse sysfs device %s", name); continue; } if (major(d) != maj || minor(d) != min) continue; closedir(dir); return affinity_class(mask, "block", name); } closedir(dir); numa_warn(W_blockdev5, "Cannot find block device %x:%x in sysfs for `%s'", maj, min, file); return -1; }
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number) { int rc = -EPERM; int xid; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; if (!old_valid_dev(device_number)) return -EINVAL; xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); if (full_path == NULL) rc = -ENOMEM; else if (pTcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = mode & ~current->fs->umask, .ctime = NO_CHANGE_64, .atime = NO_CHANGE_64, .mtime = NO_CHANGE_64, .device = device_number, }; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { args.uid = (__u64) current->fsuid; args.gid = (__u64) current->fsgid; } else { args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, xid); if (pTcon->nocase) direntry->d_op = &cifs_ci_dentry_ops; else direntry->d_op = &cifs_dentry_ops; if (rc == 0) d_instantiate(direntry, newinode); } } else { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { int oplock = 0; u16 fileHandle; FILE_ALL_INFO *buf; cFYI(1, ("sfu compat create special file")); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (buf == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; } rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, /* fail if exists */ GENERIC_WRITE /* BB would WRITE_OWNER | WRITE_DAC be better? */, /* Create a file and set the file attribute to SYSTEM */ CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB FIXME - add handling for backlevel servers which need legacy open and check for all calls to SMBOpen for fallback to SMBLeagcyOpen */ if (!rc) { /* BB Do not bother to decode buf since no local inode yet to put timestamps in, but we can reuse it safely */ unsigned int bytes_written; struct win_dev *pdev; pdev = (struct win_dev *)buf; if (S_ISCHR(mode)) { memcpy(pdev->type, "IntxCHR", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, pTcon, fileHandle, sizeof(struct win_dev), 0, &bytes_written, (char *)pdev, NULL, 0); } else if (S_ISBLK(mode)) { memcpy(pdev->type, "IntxBLK", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, pTcon, fileHandle, sizeof(struct win_dev), 0, &bytes_written, (char *)pdev, NULL, 0); } /* else if(S_ISFIFO */ CIFSSMBClose(xid, pTcon, fileHandle); d_drop(direntry); } kfree(buf); /* add code here to set EAs */ } } kfree(full_path); FreeXid(xid); return rc; }
static int process_directory(int parent, const char *path, int fixstats) { DIR *dir; struct dirent *entry; char *secontext = NULL; nDirectories++; dir = opendir(path); if(dir) { while((entry = readdir(dir)) != NULL) { /* Ignore . and .. */ if(strcmp(entry->d_name,".") && strcmp(entry->d_name,"..")) { char full_name[500]; char *suffix, dest_name[500]; int ret; struct stat stats; int equivalentObj; int newObj; sprintf(full_name,"%s/%s",path,entry->d_name); lstat(full_name,&stats); if (sehnd) { suffix = full_name + seprefixlen; ret = snprintf(dest_name, sizeof dest_name, "%s%s", mntpoint, suffix); if (ret < 0 || (size_t) ret >= sizeof dest_name) { fprintf(stderr, "snprintf failed on %s%s\n", mntpoint, suffix); exit(1); } char *sepath = NULL; if (dest_name[0] == '/') sepath = strdup(dest_name); else if (asprintf(&sepath, "/%s", dest_name) < 0) sepath = NULL; if (!sepath) { perror("malloc"); exit(1); } if (selabel_lookup(sehnd, &secontext, sepath, stats.st_mode) < 0) { perror("selabel_lookup"); free(sepath); exit(1); } free(sepath); } if(S_ISLNK(stats.st_mode) || S_ISREG(stats.st_mode) || S_ISDIR(stats.st_mode) || S_ISFIFO(stats.st_mode) || S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode) || S_ISSOCK(stats.st_mode)) { newObj = obj_id++; nObjects++; if (fixstats) { fix_stat(full_name, &stats); } //printf("Object %d, %s is a ",newObj,full_name); /* We're going to create an object for it */ if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0) { /* we need to make a hard link */ //printf("hard link to object %d\n",equivalentObj); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL, secontext); } else { add_obj_to_list(stats.st_dev,stats.st_ino,newObj); if(S_ISLNK(stats.st_mode)) { char symname[500]; memset(symname,0, sizeof(symname)); readlink(full_name,symname,sizeof(symname) -1); //printf("symlink to \"%s\"\n",symname); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname, secontext); } else if(S_ISREG(stats.st_mode)) { //printf("file, "); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL, secontext); if(error >= 0) { int h; __u8 bytes[chunkSize]; int nBytes; int chunk = 0; h = open(full_name,O_RDONLY); if(h >= 0) { memset(bytes,0xff,sizeof(bytes)); while((nBytes = read(h,bytes,sizeof(bytes))) > 0) { chunk++; write_chunk(bytes,newObj,chunk,nBytes); memset(bytes,0xff,sizeof(bytes)); } if(nBytes < 0) error = nBytes; //printf("%d data chunks written\n",chunk); } else { perror("Error opening file"); } close(h); } } else if(S_ISSOCK(stats.st_mode)) { //printf("socket\n"); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext); } else if(S_ISFIFO(stats.st_mode)) { //printf("fifo\n"); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext); } else if(S_ISCHR(stats.st_mode)) { //printf("character device\n"); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext); } else if(S_ISBLK(stats.st_mode)) { //printf("block device\n"); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext); } else if(S_ISDIR(stats.st_mode)) { //printf("directory\n"); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL, secontext); // NCB modified 10/9/2001 process_directory(1,full_name); process_directory(newObj,full_name,fixstats); } } } else { //printf(" we don't handle this type\n"); } } } closedir(dir); } return 0; }
static int jffs2_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { int err; struct nameidata nd; int mtdnr; if (!dev_name) return -EINVAL; D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); /* The preferred way of mounting in future; especially when CONFIG_BLK_DEV is implemented - we specify the underlying MTD device by number or by name, so that we don't require block device support to be present in the kernel. */ /* FIXME: How to do the root fs this way? */ if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { /* Probably mounting without the blkdev crap */ if (dev_name[3] == ':') { struct mtd_info *mtd; /* Mount by MTD device name */ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { mtd = get_mtd_device(NULL, mtdnr); if (!IS_ERR(mtd)) { if (!strcmp(mtd->name, dev_name+4)) return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); put_mtd_device(mtd); } } printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); } else if (isdigit(dev_name[3])) { /* Mount by MTD device number name */ char *endptr; mtdnr = simple_strtoul(dev_name+3, &endptr, 0); if (!*endptr) { /* It was a valid number */ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); } } } /* Try the old way - the hack where we allowed users to mount /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", err, nd.dentry->d_inode)); if (err) return err; err = -EINVAL; if (!S_ISBLK(nd.dentry->d_inode->i_mode)) goto out; if (nd.mnt->mnt_flags & MNT_NODEV) { err = -EACCES; goto out; } if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { if (!(flags & MS_SILENT)) printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", dev_name); goto out; } mtdnr = iminor(nd.dentry->d_inode); path_release(&nd); return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); out: path_release(&nd); return err; }
//获取文件属性并打印 void display_attribute(struct stat *buf, char *path) { char time[32]; struct passwd *psd; struct group *grp; //获取并打印文件类型 if (S_ISLNK(buf->st_mode)) { printf("l"); } else if (S_ISREG(buf->st_mode)) { printf("-"); } else if (S_ISDIR(buf->st_mode)) { printf("d"); } else if (S_ISCHR(buf->st_mode)) { printf("c"); } else if (S_ISBLK(buf->st_mode)) { printf("b"); } else if (S_ISFIFO(buf->st_mode)) { printf("f"); } else if (S_ISSOCK(buf->st_mode)) { printf("s"); } //获取所有者的权限 if (buf->st_mode & S_IRUSR) { printf("r"); } else { printf("-"); } if (buf->st_mode & S_IWUSR) { printf("w"); } else { printf("-"); } if (buf->st_mode & S_IXUSR) { printf("x"); } else { printf("-"); } //获取组权限 if (buf->st_mode & S_IRGRP) { printf("r"); } else { printf("-"); } if (buf->st_mode & S_IWGRP) { printf("w"); } else { printf("-"); } if (buf->st_mode & S_IXGRP) { printf("x"); } else { printf("-"); } //获取其他用户权限 if (buf->st_mode & S_IROTH) { printf("r"); } else { printf("-"); } if (buf->st_mode & S_IWOTH) { printf("w"); } else { printf("-"); } if (buf->st_mode & S_IXOTH) { printf("x"); } else { printf("-"); } printf(" "); printf("%5lu ", buf->st_nlink); //打印文件连接数 //根据uid,gid获取用户名和组名 psd = getpwuid(buf->st_uid); grp = getgrgid(buf->st_gid); printf("%-s\t", psd -> pw_name); printf("%-s\t", grp -> gr_name); printf("%10ld ", buf->st_size); //打印文件大小 strcpy(time, ctime(&buf -> st_mtime)); time[(strlen(time)) - 1] = '\0'; printf("%s ", time); //打印时间 printf("%s\n", path); //打印文件名 }