From 5f5e2a24b880fd895aaa8ef1f7429ad91067253f Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Fri, 19 Nov 2010 09:51:46 +0100 Subject: [PATCH 1/1] ad find --- bin/ad/Makefile.am | 1 + bin/ad/ad.c | 4 +- bin/ad/ad_find.c | 106 ++++++++++++++++++++ include/atalk/cnid.h | 167 +++++++++---------------------- include/atalk/cnid_dbd_private.h | 4 +- libatalk/cnid/cnid.c | 20 +++- libatalk/cnid/dbd/cnid_dbd.c | 54 ++++++++++ libatalk/cnid/dbd/cnid_dbd.h | 30 +++--- 8 files changed, 244 insertions(+), 142 deletions(-) create mode 100644 bin/ad/ad_find.c diff --git a/bin/ad/Makefile.am b/bin/ad/Makefile.am index db363aea..7e6fe922 100644 --- a/bin/ad/Makefile.am +++ b/bin/ad/Makefile.am @@ -7,6 +7,7 @@ bin_PROGRAMS = ad ad_SOURCES = \ ad.c \ + ad_find.c \ ad_util.c \ ad_ls.c \ ad_cp.c \ diff --git a/bin/ad/ad.c b/bin/ad/ad.c index add592a2..71a0f744 100644 --- a/bin/ad/ad.c +++ b/bin/ad/ad.c @@ -35,7 +35,7 @@ static void usage_main(void) { - printf("Usage: ad ls|cp|rm|mv [file|dir, ...]\n"); + printf("Usage: ad ls|cp|rm|mv|find [file|dir, ...]\n"); } int main(int argc, char **argv) @@ -55,6 +55,8 @@ int main(int argc, char **argv) return ad_rm(argc - 1, argv + 1); else if (STRCMP(argv[1], ==, "mv")) return ad_mv(argc, argv); + else if (STRCMP(argv[1], ==, "find")) + return ad_find(argc, argv); else { usage_main(); return 1; diff --git a/bin/ad/ad_find.c b/bin/ad/ad_find.c new file mode 100644 index 00000000..16dbce7f --- /dev/null +++ b/bin/ad/ad_find.c @@ -0,0 +1,106 @@ +/* + Copyright (c) 2010 Frank Lahm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "ad.h" + +static volatile sig_atomic_t alarmed; + +/* + SIGNAL handling: + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. +*/ + +static void sig_handler(int signo) +{ + alarmed = 1; + return; +} + +static void set_signal(void) +{ + struct sigaction sv; + + sv.sa_handler = sig_handler; + sv.sa_flags = SA_RESTART; + sigemptyset(&sv.sa_mask); + if (sigaction(SIGTERM, &sv, NULL) < 0) + ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); + + if (sigaction(SIGINT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGINT): %s", strerror(errno)); + + memset(&sv, 0, sizeof(struct sigaction)); + sv.sa_handler = SIG_IGN; + sigemptyset(&sv.sa_mask); + + if (sigaction(SIGABRT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); + + if (sigaction(SIGHUP, &sv, NULL) < 0) + ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); + + if (sigaction(SIGQUIT, &sv, NULL) < 0) + ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); +} + +static void usage_find(void) +{ + printf( + "Usage: ad find VOLUME_PATH NAME\n" + ); +} + +int ad_find(int argc, char **argv) +{ + int c; + afpvol_t vol; + + printf("argc: %d, argv0: %s\n", argc, argv[0]); + + if (argc != 4) { + usage_find(); + exit(1); + } + + set_signal(); + cnid_init(); + + openvol(argv[2], &vol); + cnid_find(vol.volume.v_cdb, argv[3], strlen(argv[3]) + 1); + closevol(&vol); + + return 0; +} diff --git a/include/atalk/cnid.h b/include/atalk/cnid.h index 5cd5ff70..7a0d0199 100644 --- a/include/atalk/cnid.h +++ b/include/atalk/cnid.h @@ -1,9 +1,9 @@ -/* +/* * $Id: cnid.h,v 1.15 2010-03-31 09:47:32 franklahm Exp $ * * Copyright (c) 2003 the Netatalk Team * Copyright (c) 2003 Rafal Lewczuk - * + * * This program is free software; you can redistribute and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation version 2 of the License or later @@ -11,10 +11,10 @@ * */ -/* - * This file contains all generic CNID related stuff +/* + * This file contains all generic CNID related stuff * declarations. Included: - * - CNID factory, which retrieves (eventually instantiates) + * - CNID factory, which retrieves (eventually instantiates) * CNID objects on demand * - selection of CNID backends (default, detected by volume) * - full set of CNID operations needed by server core. @@ -33,8 +33,8 @@ #define CNID_FLAG_BLOCK 0x08 /* block signals in update. */ #define CNID_FLAG_NODEV 0x10 /* don't use device number only inode */ #define CNID_FLAG_LAZY_INIT 0x20 /* */ -#define CNID_FLAG_MEMORY 0x40 /* this is a memory only db */ -#define CNID_FLAG_INODE 0x80 /* in cnid_add the inode is authoritative */ +#define CNID_FLAG_MEMORY 0x40 /* this is a memory only db */ +#define CNID_FLAG_INODE 0x80 /* in cnid_add the inode is authoritative */ #define CNID_INVALID 0 /* first valid ID */ @@ -50,29 +50,29 @@ * This is instance of CNID database object. */ struct _cnid_db { - - u_int32_t flags; /* Flags describing some CNID backend aspects. */ - char *volpath; /* Volume path this particular CNID db refers to. */ - void *_private; /* back-end speficic data */ - - cnid_t (*cnid_add)(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - char *name, const size_t, cnid_t hint); - int (*cnid_delete)(struct _cnid_db *cdb, cnid_t id); - cnid_t (*cnid_get)(struct _cnid_db *cdb, const cnid_t did, char *name, const size_t); - cnid_t (*cnid_lookup)(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - char *name, const size_t); - cnid_t (*cnid_nextid)(struct _cnid_db *cdb); - char *(*cnid_resolve)(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len); - int (*cnid_update)(struct _cnid_db *cdb, const cnid_t id, const struct stat *st, - const cnid_t did, char *name, const size_t len); - void (*cnid_close)(struct _cnid_db *cdb); - int (*cnid_getstamp)(struct _cnid_db *cdb, void *buffer, const size_t len); - cnid_t (*cnid_rebuild_add)(struct _cnid_db *, const struct stat *, const cnid_t, - char *, const size_t, cnid_t); + u_int32_t flags; /* Flags describing some CNID backend aspects. */ + char *volpath; /* Volume path this particular CNID db refers to. */ + void *_private; /* back-end speficic data */ + + cnid_t (*cnid_add) (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t, cnid_t hint); + int (*cnid_delete) (struct _cnid_db *cdb, cnid_t id); + cnid_t (*cnid_get) (struct _cnid_db *cdb, const cnid_t did, char *name, const size_t); + cnid_t (*cnid_lookup) (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t); + cnid_t (*cnid_nextid) (struct _cnid_db *cdb); + char * (*cnid_resolve) (struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len); + int (*cnid_update) (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, + const cnid_t did, char *name, const size_t len); + void (*cnid_close) (struct _cnid_db *cdb); + int (*cnid_getstamp) (struct _cnid_db *cdb, void *buffer, const size_t len); + cnid_t (*cnid_rebuild_add) (struct _cnid_db *, const struct stat *, const cnid_t, + char *, const size_t, cnid_t); + int (*cnid_find) (struct _cnid_db *cdb, const char *name, size_t len); }; typedef struct _cnid_db cnid_db; -/* +/* * Consolidation of args passedn from main cnid_open to modules cnid_XXX_open, so * that it's easier to add aditional args as required. */ @@ -88,10 +88,10 @@ struct cnid_open_args { * CNID module - represents particular CNID implementation */ struct _cnid_module { - char *name; - struct list_head db_list; /* CNID modules are also stored on a bidirectional list. */ - struct _cnid_db *(*cnid_open)(struct cnid_open_args *args); - u_int32_t flags; /* Flags describing some CNID backend aspects. */ + char *name; + struct list_head db_list; /* CNID modules are also stored on a bidirectional list. */ + struct _cnid_db *(*cnid_open)(struct cnid_open_args *args); + u_int32_t flags; /* Flags describing some CNID backend aspects. */ }; typedef struct _cnid_module cnid_module; @@ -107,98 +107,21 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags, - const char *cnidsrv, /* Only for dbd */ - const char *cnidport); /* Only for dbd */ - -cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - const char *name, const size_t len, cnid_t hint); - -int cnid_delete(struct _cnid_db *cdb, cnid_t id); - -cnid_t cnid_get (struct _cnid_db *cdb, const cnid_t did, char *name,const size_t len); - -int cnid_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len); - -cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - char *name, const size_t len); - -char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len); - -int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, - const cnid_t did, char *name, const size_t len); - + const char *cnidsrv, + const char *cnidport); +cnid_t cnid_add (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + const char *name, const size_t len, cnid_t hint); +int cnid_delete (struct _cnid_db *cdb, cnid_t id); +cnid_t cnid_get (struct _cnid_db *cdb, const cnid_t did, char *name,const size_t len); +int cnid_getstamp (struct _cnid_db *cdb, void *buffer, const size_t len); +cnid_t cnid_lookup (struct _cnid_db *cdb, const struct stat *st, const cnid_t did, + char *name, const size_t len); +char *cnid_resolve (struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len); +int cnid_update (struct _cnid_db *cdb, const cnid_t id, const struct stat *st, + const cnid_t did, char *name, const size_t len); cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, char *name, const size_t len, cnid_t hint); - - -/* This function closes a CNID database and frees all resources assigned to it. */ -void cnid_close(struct _cnid_db *db); +int cnid_find (struct _cnid_db *cdb, const char *name, size_t len); +void cnid_close (struct _cnid_db *db); #endif - -/* - * $Log: cnid.h,v $ - * Revision 1.15 2010-03-31 09:47:32 franklahm - * clustering support: new per volume option cnidserver - * - * Revision 1.14 2009/11/28 13:09:25 didg - * guard against confused DB returning junk values - * - * Revision 1.13 2009/11/24 12:18:19 didg - * add a flag parameter to cnid open functions - * - * Revision 1.12 2005/09/07 15:23:21 didg - * - * lazy init dbd database, help with pre tiger OS and a lot of volumes. - * - * Revision 1.11 2005/05/03 14:55:12 didg - * - * remove gcc warning - * - * Revision 1.10 2005/04/28 20:49:51 bfernhomberg - * - * - merge branch-netatalk-afp-3x-dev, HEAD was tagged before - * - * Revision 1.9.6.8 2005/04/25 22:33:24 lenneis - * Add a new interface to the cdb and dbd backends: cnid_rebuild_add. It - * takes dev, ino, did, name and cnid and writes these values unconditionally - * into the cnid database. To be used in a recovery tool that writes cnids - * cached in AppleDouble files back into the database. Not used yet by - * any daemons or command line utilities. - * - * Revision 1.9.6.7 2005/02/08 11:46:59 didg - * - * warnings fixes from 2.0 branch - * - * Revision 1.9.6.6 2004/02/22 18:36:37 didg - * - * small clean up - * - * Revision 1.9.6.5 2004/01/14 23:15:19 lenneis - * Check if we can get a DB stamp sucessfully in afs_openvol and fail - * the open if not. - * - * Revision 1.9.6.4 2004/01/10 07:19:31 bfernhomberg - * add cnid_init prototype - * - * Revision 1.9.6.3 2004/01/03 22:42:55 didg - * - * better errors handling in afpd for dbd cnid. - * - * Revision 1.9.6.2 2004/01/03 22:21:09 didg - * - * add nodev volume option (always use 0 for device number). - * - * Revision 1.9.6.1 2003/09/09 16:42:20 didg - * - * big merge for db frontend and unicode. - * - * Revision 1.9.4.2 2003/06/11 15:29:11 rlewczuk - * Removed obsolete parameter from cnid_add. Spotted by Didier. - * - * Revision 1.9.4.1 2003/05/29 07:53:19 rlewczuk - * Selectable CNIDs. Some refactoring. Propably needs more of refactoring, mainly - * a well designed API (current API is just an old cnid_* API enclosed in VMT). - * - */ - diff --git a/include/atalk/cnid_dbd_private.h b/include/atalk/cnid_dbd_private.h index 0607aec2..36dee3d8 100644 --- a/include/atalk/cnid_dbd_private.h +++ b/include/atalk/cnid_dbd_private.h @@ -43,7 +43,7 @@ struct cnid_dbd_rqst { ino_t ino; uint32_t type; cnid_t did; - char *name; + char *name; size_t namelen; }; @@ -51,7 +51,7 @@ struct cnid_dbd_rply { int result; cnid_t cnid; cnid_t did; - char *name; + char *name; size_t namelen; }; diff --git a/libatalk/cnid/cnid.c b/libatalk/cnid/cnid.c index ca2190e5..d4b85e35 100644 --- a/libatalk/cnid/cnid.c +++ b/libatalk/cnid/cnid.c @@ -270,9 +270,9 @@ time_t t; /* --------------- */ cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - char *name, const size_t len) + char *name, const size_t len) { -cnid_t ret; + cnid_t ret; block_signal(cdb->flags); ret = valide(cdb->cnid_lookup(cdb, st, did, name, len)); @@ -280,6 +280,22 @@ cnid_t ret; return ret; } +/* --------------- */ +int cnid_find(struct _cnid_db *cdb, const char *name, size_t len) +{ + int ret; + + if (cdb->cnid_find == NULL) { + LOG(log_error, logtype_cnid, "cnid_find not supported by CNID backend"); + return -1; + } + + block_signal(cdb->flags); + ret = cdb->cnid_find(cdb, name, len); + unblock_signal(cdb->flags); + return ret; +} + /* --------------- */ char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) { diff --git a/libatalk/cnid/dbd/cnid_dbd.c b/libatalk/cnid/dbd/cnid_dbd.c index 60f16f91..c33b601c 100644 --- a/libatalk/cnid/dbd/cnid_dbd.c +++ b/libatalk/cnid/dbd/cnid_dbd.c @@ -454,6 +454,7 @@ static struct _cnid_db *cnid_dbd_new(const char *volpath) cdb->cnid_delete = cnid_dbd_delete; cdb->cnid_get = cnid_dbd_get; cdb->cnid_lookup = cnid_dbd_lookup; + cdb->cnid_find = cnid_dbd_find; cdb->cnid_nextid = NULL; cdb->cnid_resolve = cnid_dbd_resolve; cdb->cnid_getstamp = cnid_dbd_getstamp; @@ -791,6 +792,59 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t return id; } +/* ---------------------- */ +int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t len) +{ + CNID_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + int count; + + if (!cdb || !(db = cdb->_private) || !name) { + LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (len > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_find: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_SEARCH; + + rqst.name = name; + rqst.namelen = len; + + LOG(log_debug, logtype_cnid, "cnid_find(\"%s\")", name); + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + count = rply.namelen / sizeof(cnid_t); + LOG(log_debug, logtype_cnid, "cnid_find: got %d matches", count); + break; + case CNID_DBD_RES_NOTFOUND: + count = 0; + break; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + count = -1; + break; + default: + abort(); + } + + return count; +} + /* ---------------------- */ int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st, const cnid_t did, char *name, const size_t len) diff --git a/libatalk/cnid/dbd/cnid_dbd.h b/libatalk/cnid/dbd/cnid_dbd.h index 6d43f9a0..22db5a5c 100644 --- a/libatalk/cnid/dbd/cnid_dbd.h +++ b/libatalk/cnid/dbd/cnid_dbd.h @@ -1,7 +1,6 @@ /* - * $Id: cnid_dbd.h,v 1.6 2010-03-31 09:47:32 franklahm Exp $ - * * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 * All Rights Reserved. See COPYING. */ @@ -19,19 +18,20 @@ extern struct _cnid_module cnid_dbd_module; extern struct _cnid_db *cnid_dbd_open (struct cnid_open_args *args); -extern void cnid_dbd_close (struct _cnid_db *); -extern cnid_t cnid_dbd_add (struct _cnid_db *, const struct stat *, const cnid_t, - char *, const size_t, cnid_t); -extern cnid_t cnid_dbd_get (struct _cnid_db *, const cnid_t, char *, const size_t); -extern char *cnid_dbd_resolve (struct _cnid_db *, cnid_t *, void *, size_t ); -extern int cnid_dbd_getstamp (struct _cnid_db *, void *, const size_t ); -extern cnid_t cnid_dbd_lookup (struct _cnid_db *, const struct stat *, const cnid_t, - char *, const size_t); -extern int cnid_dbd_update (struct _cnid_db *, const cnid_t, const struct stat *, - const cnid_t, char *, size_t); -extern int cnid_dbd_delete (struct _cnid_db *, const cnid_t); -extern cnid_t cnid_dbd_rebuild_add (struct _cnid_db *, const struct stat *, - const cnid_t, char *, const size_t, cnid_t); +extern void cnid_dbd_close (struct _cnid_db *); +extern cnid_t cnid_dbd_add (struct _cnid_db *, const struct stat *, const cnid_t, + char *, const size_t, cnid_t); +extern cnid_t cnid_dbd_get (struct _cnid_db *, const cnid_t, char *, const size_t); +extern char *cnid_dbd_resolve (struct _cnid_db *, cnid_t *, void *, size_t ); +extern int cnid_dbd_getstamp (struct _cnid_db *, void *, const size_t ); +extern cnid_t cnid_dbd_lookup (struct _cnid_db *, const struct stat *, const cnid_t, + char *, const size_t); +extern int cnid_dbd_find (struct _cnid_db *cdb, const char *name, size_t len); +extern int cnid_dbd_update (struct _cnid_db *, const cnid_t, const struct stat *, + const cnid_t, char *, size_t); +extern int cnid_dbd_delete (struct _cnid_db *, const cnid_t); +extern cnid_t cnid_dbd_rebuild_add(struct _cnid_db *, const struct stat *, + const cnid_t, char *, const size_t, cnid_t); /* FIXME: These functions could be static in cnid_dbd.c */ -- 2.39.2